Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.

This commit is contained in:
LFeenanEA 2025-02-27 17:34:39 +00:00
parent 2e338c00cb
commit 3d0ee53a05
No known key found for this signature in database
GPG key ID: C6EBE8C2EA08F7E0
6072 changed files with 2283311 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,208 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// AIDock.h
// Docking behavior
// Author: Michael S. Booth, February 2002
#pragma once
#ifndef _AI_DOCK_H_
#define _AI_DOCK_H_
#include "Common/GameMemory.h"
#include "GameLogic/AIStateMachine.h"
/**
* The states of the Docking state machine.
*/
enum
{
AI_DOCK_APPROACH, ///< given a queue pos, move to it
AI_DOCK_WAIT_FOR_CLEARANCE, ///< wait for dock to give us enter clearance
AI_DOCK_ADVANCE_POSITION, ///< Advance in approach position as line moves forward
AI_DOCK_MOVE_TO_ENTRY, ///< move to the dock entrance
AI_DOCK_MOVE_TO_DOCK, ///< move to the actual dock position
AI_DOCK_PROCESS_DOCK, ///< invoke the dock's action until it is done
AI_DOCK_MOVE_TO_EXIT, ///< move to the dock exit, can exit the dock machine
AI_DOCK_MOVE_TO_RALLY ///< Move to rally if desired, exit the dock machine no matter what
};
//-----------------------------------------------------------------------------------------------------------
/**
* The docking state machine.
*/
class AIDockMachine : public StateMachine
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AIDockMachine, "AIDockMachinePool" );
public:
/**
* The implementation of this constructor defines the states
* used by this machine.
*/
AIDockMachine( Object *owner );
static Bool ableToAdvance( State *thisState, void* userData ); // Condition for scooting forward in line while waiting
virtual void halt(void); ///< Stops the state machine & disables it in preparation for deleting it.
Int m_approachPosition; ///< The Approach Position I am holding, to make scoot forward checks quicker.
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
};
// Please do not use these states in some other machine. I know that wouldn't even make sense, but they
// cast their getMachine to an AIDock machine to store stuff across states so you'd crash.
//-----------------------------------------------------------------------------------------------------------
class AIDockApproachState : public AIInternalMoveToState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIDockApproachState, "AIDockApproachState")
public:
AIDockApproachState( StateMachine *machine ) : AIInternalMoveToState( machine, "AIDockApproachState" ) { }
virtual StateReturnType onEnter( void );
virtual void onExit( StateExitType status );
virtual StateReturnType update( void );
protected:
// snapshot interface STUBBED.
virtual void crc( Xfer *xfer ){};
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess(){};
};
EMPTY_DTOR(AIDockApproachState)
//-----------------------------------------------------------------------------------------------------------
class AIDockWaitForClearanceState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIDockWaitForClearanceState, "AIDockWaitForClearanceState")
public:
AIDockWaitForClearanceState( StateMachine *machine ) : State( machine, "AIDockWaitForClearanceState" ), m_enterFrame(0) { }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
UnsignedInt m_enterFrame;
protected:
// snapshot interface STUBBED.
virtual void crc( Xfer *xfer ){};
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess(){};
};
EMPTY_DTOR(AIDockWaitForClearanceState)
//-----------------------------------------------------------------------------------------------------------
class AIDockAdvancePositionState : public AIInternalMoveToState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIDockAdvancePositionState, "AIDockAdvancePositionState")
public:
AIDockAdvancePositionState( StateMachine *machine ) : AIInternalMoveToState( machine, "AIDockApproachState" ) { }
virtual StateReturnType onEnter( void );
virtual void onExit( StateExitType status );
virtual StateReturnType update( void );
};
EMPTY_DTOR(AIDockAdvancePositionState)
//-----------------------------------------------------------------------------------------------------------
class AIDockMoveToEntryState : public AIInternalMoveToState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIDockMoveToEntryState, "AIDockMoveToEntryState")
public:
AIDockMoveToEntryState( StateMachine *machine ) : AIInternalMoveToState( machine, "AIDockMoveToEntryState" ) { }
virtual StateReturnType onEnter( void );
virtual void onExit( StateExitType status );
virtual StateReturnType update( void );
};
EMPTY_DTOR(AIDockMoveToEntryState)
//-----------------------------------------------------------------------------------------------------------
class AIDockMoveToDockState : public AIInternalMoveToState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIDockMoveToDockState, "AIDockMoveToDockState")
public:
AIDockMoveToDockState( StateMachine *machine ) : AIInternalMoveToState( machine, "AIDockMoveToDockState" ) { }
virtual StateReturnType onEnter( void );
virtual void onExit( StateExitType status );
virtual StateReturnType update( void );
};
EMPTY_DTOR(AIDockMoveToDockState)
//-----------------------------------------------------------------------------------------------------------
class AIDockMoveToRallyState : public AIInternalMoveToState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIDockMoveToRallyState, "AIDockMoveToRallyState")
public:
AIDockMoveToRallyState( StateMachine *machine ) : AIInternalMoveToState( machine, "AIDockMoveToRallyState" ) { }
virtual StateReturnType onEnter( void );
virtual void onExit( StateExitType status );
virtual StateReturnType update( void );
};
EMPTY_DTOR(AIDockMoveToRallyState)
//-----------------------------------------------------------------------------------------------------------
class AIDockProcessDockState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIDockProcessDockState, "AIDockProcessDockState")
public:
AIDockProcessDockState( StateMachine *machine );
virtual StateReturnType onEnter( void );
virtual void onExit( StateExitType status );
virtual StateReturnType update( void );
void setNextDockActionFrame();//This puts a delay between callings of Action to tweak the speed of docking.
UnsignedInt m_nextDockActionFrame;// In the unlikely event of saving a game in the middle of docking, you may
// complete a Action a few frames sooner than you would have: It does not need to be saved.
Object* findMyDrone();
protected:
// snapshot interface STUBBED.
virtual void crc( Xfer *xfer ){};
virtual void xfer( Xfer *xfer ){XferVersion cv = 1; XferVersion v = cv; xfer->xferVersion( &v, cv );}
virtual void loadPostProcess(){};
private:
ObjectID m_droneID; ///< If I have a drone, the drone will get repaired too.
};
EMPTY_DTOR(AIDockProcessDockState)
//-----------------------------------------------------------------------------------------------------------
class AIDockMoveToExitState : public AIInternalMoveToState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIDockMoveToExitState, "AIDockMoveToExitState")
public:
AIDockMoveToExitState( StateMachine *machine ) : AIInternalMoveToState( machine, "AIDockMoveToExitState" ) { }
virtual StateReturnType onEnter( void );
virtual void onExit( StateExitType status );
virtual StateReturnType update( void );
};
EMPTY_DTOR(AIDockMoveToExitState)
//-----------------------------------------------------------------------------------------------------------
#endif // _AI_DOCK_H_

View file

@ -0,0 +1,280 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AIGuard.h
/*---------------------------------------------------------------------------*/
/* EA Pacific */
/* Confidential Information */
/* Copyright (C) 2001 - All Rights Reserved */
/* DO NOT DISTRIBUTE */
/*---------------------------------------------------------------------------*/
/* Project: RTS3 */
/* File name: AIGuard.h */
/* Created: John K. McDonald, Jr., 3/29/2002 */
/* Desc: // Define Guard states for AI */
/* Revision History: */
/* 3/29/2002 : Initial creation */
/*---------------------------------------------------------------------------*/
#pragma once
#ifndef _H_AIGUARD_
#define _H_AIGUARD_
// INCLUDES ///////////////////////////////////////////////////////////////////
#include "Common/GameMemory.h"
#include "GameLogic/AIStateMachine.h"
#include "GameLogic/GameLogic.h"
#include "GameLogic/Object.h"
#include "GameLogic/AI.h"
// DEFINES ////////////////////////////////////////////////////////////////////
// TYPE DEFINES ///////////////////////////////////////////////////////////////
enum
{
// prevent collisions with other states that we might use, (namely AI_IDLE)
AI_GUARD_INNER = 5000, ///< Attack anything within this area till death
AI_GUARD_IDLE, ///< Wait till something shows up to attack.
AI_GUARD_OUTER, ///< Attack anything within this area that has been aggressive, until the timer expires
AI_GUARD_RETURN, ///< Restore to a position within the inner circle
AI_GUARD_GET_CRATE, ///< Pick up a crate from an enemy we killed.
AI_GUARD_ATTACK_AGGRESSOR, ///< Attack something that attacked me (that I can attack)
};
//--------------------------------------------------------------------------------------
class ExitConditions : public AttackExitConditionsInterface
{
public:
enum ExitConditionsEnum
{
ATTACK_ExitIfOutsideRadius = 0x01,
ATTACK_ExitIfExpiredDuration = 0x02,
ATTACK_ExitIfNoUnitFound = 0x04
};
Int m_conditionsToConsider;
Coord3D m_center; // can be updated at any time by owner
Real m_radiusSqr; // can be updated at any time by owner
UnsignedInt m_attackGiveUpFrame; // frame at which we give up (if using)
ExitConditions() : m_attackGiveUpFrame(0), m_conditionsToConsider(0), m_radiusSqr(0.0f)
{
//Added By Sadullah Nader
// Initializations missing and needed
m_center.zero();
}
virtual Bool shouldExit(const StateMachine* machine) const;
};
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------
class AIGuardMachine : public StateMachine
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AIGuardMachine, "AIGuardMachinePool" );
private:
ObjectID m_targetToGuard;
const PolygonTrigger * m_areaToGuard;
Coord3D m_positionToGuard;
ObjectID m_nemesisToAttack;
GuardMode m_guardMode;
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
public:
/**
* The implementation of this constructor defines the states
* used by this machine.
*/
AIGuardMachine( Object *owner );
Object* findTargetToGuardByID( void ) { return TheGameLogic->findObjectByID(m_targetToGuard); }
void setTargetToGuard( const Object *object ) { m_targetToGuard = object ? object->getID() : INVALID_ID; }
const Coord3D *getPositionToGuard( void ) const { return &m_positionToGuard; }
void setTargetPositionToGuard( const Coord3D *pos) { m_positionToGuard = *pos; }
const PolygonTrigger *getAreaToGuard( void ) const { return m_areaToGuard; }
void setAreaToGuard( const PolygonTrigger *area) { m_areaToGuard = area; }
void setNemesisID(ObjectID id) { m_nemesisToAttack = id; }
ObjectID getNemesisID() const { return m_nemesisToAttack; }
GuardMode getGuardMode() const { return m_guardMode; }
void setGuardMode(GuardMode guardMode) { m_guardMode = guardMode; }
Bool lookForInnerTarget(void);
static Real getStdGuardRange(const Object* obj);
};
//--------------------------------------------------------------------------------------
class AIGuardInnerState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardInnerState, "AIGuardInnerState")
public:
AIGuardInnerState( StateMachine *machine ) : State( machine, "AIGuardInner" )
{
m_attackState = 0;
m_enterState = 0;
}
virtual Bool isAttack() const { return m_attackState ? m_attackState->isAttack() : FALSE; }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AIGuardMachine* getGuardMachine() { return (AIGuardMachine*)getMachine(); }
ExitConditions m_exitConditions;
AIAttackState *m_attackState;
AIEnterState *m_enterState;
};
EMPTY_DTOR(AIGuardInnerState)
//--------------------------------------------------------------------------------------
class AIGuardIdleState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardIdleState, "AIGuardIdleState")
public:
AIGuardIdleState( StateMachine *machine ) : State( machine, "AIGuardIdleState" ) { }
virtual Bool isAttack() const { return FALSE; }
virtual Bool isGuardIdle() const { return TRUE; }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AIGuardMachine* getGuardMachine() { return (AIGuardMachine*)getMachine(); }
UnsignedInt m_nextEnemyScanTime;
Coord3D m_guardeePos; ///< Where the object we are guarding was last.
};
EMPTY_DTOR(AIGuardIdleState)
//--------------------------------------------------------------------------------------
class AIGuardOuterState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardOuterState, "AIGuardOuterState")
public:
AIGuardOuterState( StateMachine *machine ) : State( machine, "AIGuardOuter" )
{
m_attackState = NULL;
}
virtual Bool isAttack() const { return m_attackState ? m_attackState->isAttack() : FALSE; }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AIGuardMachine* getGuardMachine() { return (AIGuardMachine*)getMachine(); }
ExitConditions m_exitConditions;
AIAttackState *m_attackState;
};
EMPTY_DTOR(AIGuardOuterState)
//--------------------------------------------------------------------------------------
class AIGuardReturnState : public AIInternalMoveToState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardReturnState, "AIGuardReturnState")
private:
AIGuardMachine* getGuardMachine() { return (AIGuardMachine*)getMachine(); }
public:
AIGuardReturnState( StateMachine *machine ) : AIInternalMoveToState( machine, "AIGuardReturn" )
{
m_nextReturnScanTime = 0;
}
virtual Bool isAttack() const { return FALSE; }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
UnsignedInt m_nextReturnScanTime;
};
EMPTY_DTOR(AIGuardReturnState)
//--------------------------------------------------------------------------------------
class AIGuardPickUpCrateState : public AIPickUpCrateState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardPickUpCrateState, "AIGuardPickUpCrateState")
public:
AIGuardPickUpCrateState( StateMachine *machine );
virtual Bool isAttack() const { return FALSE; }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
};
EMPTY_DTOR(AIGuardPickUpCrateState)
//--------------------------------------------------------------------------------------
class AIGuardAttackAggressorState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardAttackAggressorState, "AIGuardAttackAggressorState")
public:
AIGuardAttackAggressorState( StateMachine *machine );
virtual Bool isAttack() const { return m_attackState ? m_attackState->isAttack() : FALSE; }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AIGuardMachine* getGuardMachine() { return (AIGuardMachine*)getMachine(); }
ExitConditions m_exitConditions;
AIAttackState *m_attackState;
};
EMPTY_DTOR(AIGuardAttackAggressorState)
//--------------------------------------------------------------------------------------
#endif /* _H_AIGUARD_ */

View file

@ -0,0 +1,265 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AIGuardRetaliate.h
/*---------------------------------------------------------------------------*/
/* Electronic Arts Los Angeles */
/* Confidential Information */
/* Copyright (C) 2003 - All Rights Reserved */
/* DO NOT DISTRIBUTE */
/*---------------------------------------------------------------------------*/
/* Project: RTS3 */
/* File name: AIGuardRetaliate.h */
/* Created: Kris Morness July 2003 */
/* Desc: // Define Guard Retaliation states for AI */
/*---------------------------------------------------------------------------*/
#pragma once
#ifndef __AI_GUARD_RETALIATION_H
#define __AI_GUARD_RETALIATION_H
// INCLUDES ///////////////////////////////////////////////////////////////////
#include "Common/GameMemory.h"
#include "GameLogic/AIStateMachine.h"
#include "GameLogic/GameLogic.h"
#include "GameLogic/Object.h"
#include "GameLogic/AI.h"
// DEFINES ////////////////////////////////////////////////////////////////////
// TYPE DEFINES ///////////////////////////////////////////////////////////////
enum
{
// prevent collisions with other states that we might use, (namely AI_IDLE)
AI_GUARD_RETALIATE_INNER = 5000, ///< Attack anything within this area till death
AI_GUARD_RETALIATE_IDLE, ///< Wait till something shows up to attack.
AI_GUARD_RETALIATE_OUTER, ///< Attack anything within this area that has been aggressive, until the timer expires
AI_GUARD_RETALIATE_RETURN, ///< Restore to a position within the inner circle
AI_GUARD_RETALIATE_GET_CRATE, ///< Pick up a crate from an enemy we killed.
AI_GUARD_RETALIATE_ATTACK_AGGRESSOR, ///< Attack something that attacked me (that I can attack)
};
//--------------------------------------------------------------------------------------
class GuardRetaliateExitConditions : public AttackExitConditionsInterface
{
public:
enum ExitConditionsEnum
{
ATTACK_ExitIfOutsideRadius = 0x01,
ATTACK_ExitIfExpiredDuration = 0x02,
ATTACK_ExitIfNoUnitFound = 0x04
};
Int m_conditionsToConsider;
Coord3D m_center; // can be updated at any time by owner
Real m_radiusSqr; // can be updated at any time by owner
UnsignedInt m_attackGiveUpFrame; // frame at which we give up (if using)
GuardRetaliateExitConditions() : m_attackGiveUpFrame(0), m_conditionsToConsider(0), m_radiusSqr(0.0f)
{
//Added By Sadullah Nader
// Initializations missing and needed
m_center.zero();
}
virtual Bool shouldExit(const StateMachine* machine) const;
};
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------
class AIGuardRetaliateMachine : public StateMachine
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AIGuardRetaliateMachine, "AIGuardRetaliateMachinePool" );
private:
Coord3D m_positionToGuard;
ObjectID m_nemesisToAttack;
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
public:
/**
* The implementation of this constructor defines the states
* used by this machine.
*/
AIGuardRetaliateMachine( Object *owner );
virtual Bool isIdle() const;
const Coord3D *getPositionToGuard( void ) const { return &m_positionToGuard; }
void setTargetPositionToGuard( const Coord3D *pos) { m_positionToGuard = *pos; }
void setNemesisID(ObjectID id) { m_nemesisToAttack = id; }
ObjectID getNemesisID() const { return m_nemesisToAttack; }
Bool lookForInnerTarget(void);
static Real getStdGuardRange(const Object* obj);
};
//--------------------------------------------------------------------------------------
class AIGuardRetaliateInnerState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardRetaliateInnerState, "AIGuardRetaliateInnerState")
public:
AIGuardRetaliateInnerState( StateMachine *machine ) : State( machine, "AIGuardRetaliateInner" )
{
m_attackState = 0;
m_enterState = 0;
}
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AIGuardRetaliateMachine* getGuardMachine() { return (AIGuardRetaliateMachine*)getMachine(); }
GuardRetaliateExitConditions m_exitConditions;
AIAttackState *m_attackState;
AIEnterState *m_enterState;
};
EMPTY_DTOR(AIGuardRetaliateInnerState)
//--------------------------------------------------------------------------------------
class AIGuardRetaliateIdleState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardRetaliateIdleState, "AIGuardRetaliateIdleState")
public:
AIGuardRetaliateIdleState( StateMachine *machine ) : State( machine, "AIGuardRetaliateIdleState" ) { }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AIGuardRetaliateMachine* getGuardMachine() { return (AIGuardRetaliateMachine*)getMachine(); }
UnsignedInt m_nextEnemyScanTime;
Coord3D m_guardeePos; ///< Where the object we are guarding was last.
};
EMPTY_DTOR(AIGuardRetaliateIdleState)
//--------------------------------------------------------------------------------------
class AIGuardRetaliateOuterState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardRetaliateOuterState, "AIGuardRetaliateOuterState")
public:
AIGuardRetaliateOuterState( StateMachine *machine ) : State( machine, "AIGuardRetaliateOuter" )
{
m_attackState = NULL;
}
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AIGuardRetaliateMachine* getGuardMachine() { return (AIGuardRetaliateMachine*)getMachine(); }
GuardRetaliateExitConditions m_exitConditions;
AIAttackState *m_attackState;
};
EMPTY_DTOR(AIGuardRetaliateOuterState)
//--------------------------------------------------------------------------------------
class AIGuardRetaliateReturnState : public AIInternalMoveToState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardRetaliateReturnState, "AIGuardRetaliateReturnState")
private:
AIGuardRetaliateMachine* getGuardMachine() { return (AIGuardRetaliateMachine*)getMachine(); }
public:
AIGuardRetaliateReturnState( StateMachine *machine ) : AIInternalMoveToState( machine, "AIGuardRetaliateReturn" )
{
m_nextReturnScanTime = 0;
}
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
UnsignedInt m_nextReturnScanTime;
};
EMPTY_DTOR(AIGuardRetaliateReturnState)
//--------------------------------------------------------------------------------------
class AIGuardRetaliatePickUpCrateState : public AIPickUpCrateState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardRetaliatePickUpCrateState, "AIGuardRetaliatePickUpCrateState")
public:
AIGuardRetaliatePickUpCrateState( StateMachine *machine );
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
};
EMPTY_DTOR(AIGuardRetaliatePickUpCrateState)
//--------------------------------------------------------------------------------------
class AIGuardRetaliateAttackAggressorState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AIGuardRetaliateAttackAggressorState, "AIGuardRetaliateAttackAggressorState")
public:
AIGuardRetaliateAttackAggressorState( StateMachine *machine );
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
#ifdef STATE_MACHINE_DEBUG
virtual AsciiString getName() const ;
#endif
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AIGuardRetaliateMachine* getGuardMachine() { return (AIGuardRetaliateMachine*)getMachine(); }
GuardRetaliateExitConditions m_exitConditions;
AIAttackState *m_attackState;
};
EMPTY_DTOR(AIGuardRetaliateAttackAggressorState)
//--------------------------------------------------------------------------------------
#endif

View file

@ -0,0 +1,985 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// AIPathfind.h
// AI pathfinding system
// Author: Michael S. Booth, October 2001
#pragma once
#ifndef _PATHFIND_H_
#define _PATHFIND_H_
#include "Common/GameType.h"
#include "Common/GameMemory.h"
#include "Common/Snapshot.h"
//#include "GameLogic/Locomotor.h" // no, do not include this, unless you like long recompiles
#include "GameLogic/LocomotorSet.h"
#include "GameLogic/GameLogic.h"
class Bridge;
class Object;
class Weapon;
class PathfindZoneManager;
// How close is close enough when moving.
#define PATHFIND_CLOSE_ENOUGH 1.0f
#define PATH_MAX_PRIORITY 0x7FFFFFFF
#define INFANTRY_MOVES_THROUGH_INFANTRY
typedef UnsignedShort zoneStorageType;
//----------------------------------------------------------------------------------------------------------
/**
* PathNodes are used to create a final Path to return from the
* pathfinder. Note that these are not used during the A* search.
*/
class PathNode : public MemoryPoolObject
{
public:
PathNode();
Coord3D *getPosition( void ) { return &m_pos; } ///< return position of this node
const Coord3D *getPosition( void ) const { return &m_pos; } ///< return position of this node
void setPosition( const Coord3D *pos ) { m_pos = *pos; } ///< set the position of this path node
const Coord3D *computeDirectionVector( void ); ///< compute direction to next node
PathNode *getNext( void ) { return m_next; } ///< return next node in the path
PathNode *getPrevious( void ) { return m_prev; } ///< return previous node in the path
const PathNode *getNext( void ) const { return m_next; } ///< return next node in the path
const PathNode *getPrevious( void ) const { return m_prev; } ///< return previous node in the path
PathfindLayerEnum getLayer( void ) const { return m_layer; } ///< return layer of this node.
void setLayer( PathfindLayerEnum layer ) { m_layer = layer; } ///< set the layer of this path node
void setNextOptimized( PathNode *node );
PathNode *getNextOptimized(Coord2D* dir = NULL, Real* dist = NULL) ///< return next node in optimized path
{
if (dir)
*dir = m_nextOptiDirNorm2D;
if (dist)
*dist = m_nextOptiDist2D;
return m_nextOpti;
}
const PathNode *getNextOptimized(Coord2D* dir = NULL, Real* dist = NULL) const ///< return next node in optimized path
{
if (dir)
*dir = m_nextOptiDirNorm2D;
if (dist)
*dist = m_nextOptiDist2D;
return m_nextOpti;
}
void setCanOptimize(Bool canOpt) { m_canOptimize = canOpt;}
Bool getCanOptimize( void ) const { return m_canOptimize;}
/// given a list, prepend this node, return new list
PathNode *prependToList( PathNode *list );
/// given a list, append this node, return new list. slow implementation.
/// @todo optimize this
PathNode *appendToList( PathNode *list );
/// given a node, append to this node
void append( PathNode *list );
public:
mutable Int m_id; // Used in Path::xfer() to save & recreate the path list.
private:
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( PathNode, "PathNodePool" ); ///< @todo Set real numbers for mem alloc
PathNode* m_nextOpti; ///< next node in the optimized path
PathNode* m_next; ///< next node in the path
PathNode* m_prev; ///< previous node in the path
Coord3D m_pos; ///< position of node in space
PathfindLayerEnum m_layer; ///< Layer for this section.
Bool m_canOptimize; ///< True if this cell can be optimized out.
Real m_nextOptiDist2D; ///< if nextOpti is nonnull, the dist to it.
Coord2D m_nextOptiDirNorm2D; ///< if nextOpti is nonnull, normalized dir vec towards it.
};
// this doesn't actually seem to be a particularly useful win,
// performance-wise, so I didn't enable it. (srj)
#define NO_CPOP_STARTS_FROM_PREV_SEG
struct ClosestPointOnPathInfo
{
Real distAlongPath;
Coord3D posOnPath;
PathfindLayerEnum layer;
};
/**
* This class encapsulates a "path" returned by the Pathfinder.
*/
class Path : public MemoryPoolObject, public Snapshot
{
public:
Path();
PathNode *getFirstNode( void ) { return m_path; }
PathNode *getLastNode( void ) { return m_pathTail; }
void updateLastNode( const Coord3D *pos );
void prependNode( const Coord3D *pos, PathfindLayerEnum layer ); ///< Create a new node at the head of the path
void appendNode( const Coord3D *pos, PathfindLayerEnum layer ); ///< Create a new node at the end of the path
void setBlockedByAlly(Bool blocked) {m_blockedByAlly = blocked;}
Bool getBlockedByAlly(void) {return m_blockedByAlly;}
void optimize( const Object *obj, LocomotorSurfaceTypeMask acceptableSurfaces, Bool blocked ); ///< Optimize the path to discard redundant nodes
void optimizeGroundPath( Bool crusher, Int diameter ); ///< Optimize the ground path to discard redundant nodes
/// Given a location, return nearest location on path, and along-path dist to end as function result
void computePointOnPath( const Object *obj, const LocomotorSet& locomotorSet, const Coord3D& pos, ClosestPointOnPathInfo& out);
/// Given a location, return nearest location on path, and along-path dist to end as function result
void peekCachedPointOnPath( Coord3D& pos ) const {pos = m_cpopOut.posOnPath;}
/// Given a flight path, compute the distance to goal (0 if we are past it) & return the goal pos.
Real computeFlightDistToGoal( const Coord3D *pos, Coord3D& goalPos );
/// Given a location, return closest location on path, and along-path dist to end as function result
void markOptimized(void) {m_isOptimized = true;}
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
protected:
enum {MAX_CPOP=20}; ///< Max times we will return the cached cpop.
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( Path, "PathPool" ); ///< @todo Set real numbers for mem alloc
PathNode* m_path; ///< The list of PathNode objects that define the path
PathNode* m_pathTail;
Bool m_isOptimized; ///< True if the path has been optimized
Bool m_blockedByAlly; ///< An ally needs to move off of this path.
// caching info for computePointOnPath.
Bool m_cpopValid;
Int m_cpopCountdown; ///< We only return the same cpop MAX_CPOP times. It is occasionally possible to get stuck.
Coord3D m_cpopIn;
ClosestPointOnPathInfo m_cpopOut;
const PathNode* m_cpopRecentStart;
};
//----------------------------------------------------------------------------------------------------------
// See GameType.h for
// enum {LAYER_INVALID = 0, LAYER_GROUND = 1, LAYER_TOP=2 };
// Fits in 4 bits for now
enum {MAX_WALL_PIECES = 128};
class PathfindCellInfo
{
friend class PathfindCell;
public:
static void allocateCellInfos(void);
static void releaseCellInfos(void);
static PathfindCellInfo * getACellInfo(PathfindCell *cell, const ICoord2D &pos);
static void releaseACellInfo(PathfindCellInfo *theInfo);
protected:
static PathfindCellInfo *s_infoArray;
static PathfindCellInfo *s_firstFree; ///<
PathfindCellInfo *m_nextOpen, *m_prevOpen; ///< for A* "open" list, shared by closed list
PathfindCellInfo *m_pathParent; ///< "parent" cell from pathfinder
PathfindCell *m_cell; ///< Cell this info belongs to currently.
UnsignedShort m_totalCost, m_costSoFar; ///< cost estimates for A* search
/// have to include cell's coordinates, since cells are often accessed via pointer only
ICoord2D m_pos;
ObjectID m_goalUnitID; ///< The objectID of the ground unit whose goal this is.
ObjectID m_posUnitID; ///< The objectID of the ground unit that is occupying this cell.
ObjectID m_goalAircraftID; ///< The objectID of the aircraft whose goal this is.
ObjectID m_obstacleID; ///< the object ID who overlaps this cell
UnsignedInt m_isFree:1;
UnsignedInt m_blockedByAlly:1;///< True if this cell is blocked by an allied unit.
UnsignedInt m_obstacleIsFence:1;///< True if occupied by a fence.
UnsignedInt m_obstacleIsTransparent:1;///< True if obstacle is transparent (undefined if obstacleid is invalid)
/// @todo Do we need both mark values in this cell? Can't store a single value and compare it?
UnsignedInt m_open:1; ///< place for marking this cell as on the open list
UnsignedInt m_closed:1; ///< place for marking this cell as on the closed list
};
/**
* This represents one cell in the pathfinding grid.
* These cells categorize the world into idealized cellular states,
* and are also used for efficient A* pathfinding.
* @todo Optimize memory usage of pathfind grid.
*/
class PathfindCell
{
public:
enum CellType
{
CELL_CLEAR = 0x00, ///< clear, unobstructed ground
CELL_WATER = 0x01, ///< water area
CELL_CLIFF = 0x02, ///< steep altitude change
CELL_RUBBLE = 0x03, ///< Cell is occupied by rubble.
CELL_OBSTACLE = 0x04, ///< Occupied by a structure
CELL_BRIDGE_IMPASSABLE = 0x05, ///< Piece of a bridge that is impassable.
CELL_IMPASSABLE = 0x06 ///< Just plain impassable except for aircraft.
};
enum CellFlags
{
NO_UNITS = 0x00, ///< No units in this cell.
UNIT_GOAL = 0x01, ///< A unit is heading to this cell.
UNIT_PRESENT_MOVING = 0x02, ///< A unit is moving through this cell.
UNIT_PRESENT_FIXED = 0x03, ///< A unit is stationary in this cell.
UNIT_GOAL_OTHER_MOVING = 0x05 ///< A unit is moving through this cell, and another unit has this as it's goal.
};
/// reset the cell
void reset( );
PathfindCell(void);
~PathfindCell(void);
Bool setTypeAsObstacle( Object *obstacle, Bool isFence, const ICoord2D &pos ); ///< flag this cell as an obstacle, from the given one
Bool removeObstacle( Object *obstacle ); ///< unflag this cell as an obstacle, from the given one
void setType( CellType type ); ///< set the cell type
CellType getType( void ) const { return (CellType)m_type; } ///< get the cell type
CellFlags getFlags( void ) const { return (CellFlags)m_flags; } ///< get the cell type
Bool isAircraftGoal( void) const {return m_aircraftGoal != 0;}
Bool isObstaclePresent( ObjectID objID ) const; ///< return true if the given object ID is registered as an obstacle in this cell
Bool isObstacleTransparent( ) const{return m_info?m_info->m_obstacleIsTransparent:false; } ///< return true if the obstacle in the cell is KINDOF_CAN_SEE_THROUGHT_STRUCTURE
Bool isObstacleFence( void ) const {return m_info?m_info->m_obstacleIsFence:false; }///< return true if the given obstacle in the cell is a fence.
/// Return estimated cost from given cell to reach goal cell
UnsignedInt costToGoal( PathfindCell *goal );
UnsignedInt costToHierGoal( PathfindCell *goal );
UnsignedInt costSoFar( PathfindCell *parent );
/// put self on "open" list in ascending cost order, return new list
PathfindCell *putOnSortedOpenList( PathfindCell *list );
/// remove self from "open" list
PathfindCell *removeFromOpenList( PathfindCell *list );
/// put self on "closed" list, return new list
PathfindCell *putOnClosedList( PathfindCell *list );
/// remove self from "closed" list
PathfindCell *removeFromClosedList( PathfindCell *list );
/// remove all cells from closed list.
static Int releaseClosedList( PathfindCell *list );
/// remove all cells from closed list.
static Int releaseOpenList( PathfindCell *list );
inline PathfindCell *getNextOpen(void) {return m_info->m_nextOpen?m_info->m_nextOpen->m_cell:NULL;}
inline UnsignedShort getXIndex(void) const {return m_info->m_pos.x;}
inline UnsignedShort getYIndex(void) const {return m_info->m_pos.y;}
inline Bool isBlockedByAlly(void) const {return m_info->m_blockedByAlly;}
inline void setBlockedByAlly(Bool blocked) {m_info->m_blockedByAlly = (blocked!=0);}
inline Bool getOpen(void) const {return m_info->m_open;}
inline Bool getClosed(void) const {return m_info->m_closed;}
inline UnsignedInt getCostSoFar(void) const {return m_info->m_costSoFar;}
inline UnsignedInt getTotalCost(void) const {return m_info->m_totalCost;}
inline void setCostSoFar(UnsignedInt cost) { if( m_info ) m_info->m_costSoFar = cost;}
inline void setTotalCost(UnsignedInt cost) { if( m_info ) m_info->m_totalCost = cost;}
void setParentCell(PathfindCell* parent);
void clearParentCell(void);
void setParentCellHierarchical(PathfindCell* parent);
inline PathfindCell* getParentCell(void) const {return m_info ? m_info->m_pathParent ? m_info->m_pathParent->m_cell : NULL : NULL;}
Bool startPathfind( PathfindCell *goalCell );
Bool getPinched(void) const {return m_pinched;}
void setPinched(Bool pinch) {m_pinched = pinch; }
Bool allocateInfo(const ICoord2D &pos);
void releaseInfo(void);
Bool hasInfo(void) const {return m_info!=NULL;}
zoneStorageType getZone(void) const {return m_zone;}
void setZone(zoneStorageType zone) {m_zone = zone;}
void setGoalUnit(ObjectID unit, const ICoord2D &pos );
void setGoalAircraft(ObjectID unit, const ICoord2D &pos );
void setPosUnit(ObjectID unit, const ICoord2D &pos );
inline ObjectID getGoalUnit(void) const {ObjectID id = m_info?m_info->m_goalUnitID:INVALID_ID; return id;}
inline ObjectID getGoalAircraft(void) const {ObjectID id = m_info?m_info->m_goalAircraftID:INVALID_ID; return id;}
inline ObjectID getPosUnit(void) const {ObjectID id = m_info?m_info->m_posUnitID:INVALID_ID; return id;}
inline ObjectID getObstacleID(void) const {ObjectID id = m_info?m_info->m_obstacleID:INVALID_ID; return id;}
void setLayer( PathfindLayerEnum layer ) { m_layer = layer; } ///< set the cell layer
PathfindLayerEnum getLayer( void ) const { return (PathfindLayerEnum)m_layer; } ///< get the cell layer
void setConnectLayer( PathfindLayerEnum layer ) { m_connectsToLayer = layer; } ///< set the cell layer connect id
PathfindLayerEnum getConnectLayer( void ) const { return (PathfindLayerEnum)m_connectsToLayer; } ///< get the cell layer connect id
private:
PathfindCellInfo *m_info;
zoneStorageType m_zone:14; ///< Zone. Each zone is a set of adjacent terrain type. If from & to in the same zone, you can successfully pathfind. If not,
// you still may be able to if you can cross multiple terrain types.
UnsignedShort m_aircraftGoal:1; //< This is an aircraft goal cell.
UnsignedShort m_pinched:1; //< This cell is surrounded by obstacle cells.
UnsignedByte m_type:4; ///< what type of cell terrain this is.
UnsignedByte m_flags:4; ///< what type of units are in or moving through this cell.
UnsignedByte m_connectsToLayer:4; ///< This cell can pathfind onto this layer, if > LAYER_TOP.
UnsignedByte m_layer:4; ///< Layer of this cell.
};
typedef PathfindCell *PathfindCellP;
// how close a unit has to be in z to interact with the layer.
#define LAYER_Z_CLOSE_ENOUGH_F 10.0f
/**
* This class represents a bridge in the map. This is effectively
* a sub-rectangle of the big pathfind map.
*/
class PathfindLayer
{
public:
PathfindLayer();
~PathfindLayer();
public:
void reset(void);
Bool init(Bridge *theBridge, PathfindLayerEnum layer);
void allocateCells(const IRegion2D *extent);
void allocateCellsForWallLayer(const IRegion2D *extent, ObjectID *wallPieces, Int numPieces);
void classifyCells();
void classifyWallCells(ObjectID *wallPieces, Int numPieces);
Bool setDestroyed(Bool destroyed);
Bool isUnused(void); // True if it doesn't contain a bridge.
Bool isDestroyed(void) {return m_destroyed;} // True if it has been destroyed.
PathfindCell *getCell(Int x, Int y);
Int getZone(void) {return m_zone;}
void setZone(Int zone) {m_zone = zone;}
void applyZone(void); // Propagates m_zone to all cells.
void getStartCellIndex(ICoord2D *start) {*start = m_startCell;}
void getEndCellIndex(ICoord2D *end) {*end = m_endCell;}
ObjectID getBridgeID(void);
Bool connectsZones(PathfindZoneManager *zm, const LocomotorSet& locomotorSet,Int zone1, Int zone2);
Bool isPointOnWall(ObjectID *wallPieces, Int numPieces, const Coord3D *pt);
#if defined _DEBUG || defined _INTERNAL
void doDebugIcons(void) ;
#endif
protected:
void classifyLayerMapCell( Int i, Int j , PathfindCell *cell, Bridge *theBridge);
void classifyWallMapCell( Int i, Int j, PathfindCell *cell , ObjectID *wallPieces, Int numPieces);
private:
PathfindCell *m_blockOfMapCells; ///< Pathfinding map - contains iconic representation of the map
PathfindCell **m_layerCells; ///< Pathfinding map indexes - contains matrix indexing into the map.
Int m_width; // Number of cells in x
Int m_height; // Number of cells in y
Int m_xOrigin; // Index of first cell in x
Int m_yOrigin; // Index of first cell in y
ICoord2D m_startCell; // pathfind cell indexes for center cell on the from side.
ICoord2D m_endCell; // pathfind cell indexes for center cell on the to side.
PathfindLayerEnum m_layer;
Int m_zone; // Whole bridge is in same zone.
Bridge *m_bridge; // Corresponding bridge in TerrainLogic.
Bool m_destroyed;
};
#define PATHFIND_CELL_SIZE 10
#define PATHFIND_CELL_SIZE_F 10.0f
enum { PATHFIND_QUEUE_LEN=512};
struct TCheckMovementInfo;
/**
* This class is a helper class for zone manager. It maintains information regarding the
* LocomotorSurfaceTypeMask equivalencies within a ZONE_BLOCK_SIZE x ZONE_BLOCK_SIZE area of
* cells. This is used in hierarchical pathfinding to find the best coarse path at the
* block level.
*/
class ZoneBlock
{
public:
ZoneBlock();
~ZoneBlock(); // not virtual, please don't override without making virtual. jba.
void blockCalculateZones( PathfindCell **map, PathfindLayer layers[], const IRegion2D &bounds); ///< Does zone calculations.
zoneStorageType getEffectiveZone(LocomotorSurfaceTypeMask acceptableSurfaces, Bool crusher, zoneStorageType zone) const;
void clearMarkedPassable(void) {m_markedPassable = false;}
Bool isPassable(void) {return m_markedPassable;}
void setPassable(Bool pass) {m_markedPassable = pass;}
Bool getInteractsWithBridge(void) const {return m_interactsWithBridge;}
void setInteractsWithBridge(Bool interacts) {m_interactsWithBridge = interacts;}
protected:
void allocateZones(void);
void freeZones(void);
protected:
ICoord2D m_cellOrigin;
zoneStorageType m_firstZone; // First zone in this block.
UnsignedShort m_numZones; // Number of zones in this block. If == 1, there is only one zone, and
// no zone equivalency arrays will be allocated.
UnsignedShort m_zonesAllocated;
zoneStorageType *m_groundCliffZones;
zoneStorageType *m_groundWaterZones;
zoneStorageType *m_groundRubbleZones;
zoneStorageType *m_crusherZones;
Bool m_interactsWithBridge;
Bool m_markedPassable;
};
typedef ZoneBlock *ZoneBlockP;
/**
* This class manages the zones in the map. A zone is an area in the map that
* is one contiguous type of terrain (clear, cliff, water, building). If
* a unit is in a zone, and wants to move to another location, the destination
* zone has to be the same, or it can't get there.
* There are equivalency tables for meta-zones. For example, an amphibious craft can
* travel through water and clear cells.
*/
class PathfindZoneManager
{
public:
enum {INITIAL_ZONES = 256};
enum {ZONE_BLOCK_SIZE = 10}; // Zones are calculated in blocks of 20x20. This way, the raw zone numbers can be used to
enum {UNINITIALIZED_ZONE = 0};
// compute hierarchically between the 20x20 blocks of cells. jba.
PathfindZoneManager();
~PathfindZoneManager();
void reset(void);
Bool needToCalculateZones(void) const {return m_nextFrameToCalculateZones <= TheGameLogic->getFrame() ;} ///< Returns true if the zones need to be recalculated.
void markZonesDirty( Bool insert ) ; ///< Called when the zones need to be recalculated.
void updateZonesForModify( PathfindCell **map, PathfindLayer layers[], const IRegion2D &structureBounds, const IRegion2D &globalBounds ) ; ///< Called to recalculate an area when a structure has been removed.
void calculateZones( PathfindCell **map, PathfindLayer layers[], const IRegion2D &bounds); ///< Does zone calculations.
zoneStorageType getEffectiveZone(LocomotorSurfaceTypeMask acceptableSurfaces, Bool crusher, zoneStorageType zone) const;
zoneStorageType getEffectiveTerrainZone(zoneStorageType zone) const;
zoneStorageType getNextZone(void);
void getExtent(ICoord2D &extent) const {extent = m_zoneBlockExtent;}
/// return zone relative the the block zone that this cell resides in.
zoneStorageType getBlockZone(LocomotorSurfaceTypeMask acceptableSurfaces, Bool crusher, Int cellX, Int cellY, PathfindCell **map) const;
void allocateBlocks(const IRegion2D &globalBounds);
void clearPassableFlags(void);
Bool isPassable(Int cellX, Int cellY) const;
Bool clipIsPassable(Int cellX, Int cellY) const;
void setPassable(Int cellX, Int cellY, Bool passable);
void setAllPassable(void);
void setBridge(Int cellX, Int cellY, Bool bridge);
Bool interactsWithBridge(Int cellX, Int cellY) const;
private:
void allocateZones(void);
void freeZones(void);
void freeBlocks(void);
private:
ZoneBlock *m_blockOfZoneBlocks; ///< Zone blocks - Info for hierarchical pathfinding at a "blocky" level.
ZoneBlock **m_zoneBlocks; ///< Zone blocks as a matrix - contains matrix indexing into the map.
ICoord2D m_zoneBlockExtent; ///< Zone block extents. Not the same scale as the pathfind extents.
UnsignedShort m_maxZone; ///< Max zone used.
UnsignedInt m_nextFrameToCalculateZones; ///< WHen should I recalculate, next?.
UnsignedShort m_zonesAllocated;
zoneStorageType *m_groundCliffZones;
zoneStorageType *m_groundWaterZones;
zoneStorageType *m_groundRubbleZones;
zoneStorageType *m_terrainZones;
zoneStorageType *m_crusherZones;
zoneStorageType *m_hierarchicalZones;
};
/**
* The pathfinding services interface provides access to the 3 expensive path find calls:
* findPath, findClosestPath, and findAttackPath.
* It is only available to units when their ai interface doPathfind method is called.
* This allows the pathfinder to spread out the pathfinding over a number of frames
* when a lot of units are trying to pathfind all at the same time.
*/
class PathfindServicesInterface {
public:
virtual Path *findPath( Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from,
const Coord3D *to )=0; ///< Find a short, valid path between given locations
/** Find a short, valid path to a location NEAR the to location.
This succeds when the destination is unreachable (like inside a building).
If the destination is unreachable, it will adjust the to point. */
virtual Path *findClosestPath( Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from,
Coord3D *to, Bool blocked, Real pathCostMultiplier, Bool moveAllies )=0;
/** Find a short, valid path to a location that obj can attack victim from. */
virtual Path *findAttackPath( const Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from,
const Object *victim, const Coord3D* victimPos, const Weapon *weapon )=0;
/** Patch to the exiting path from the current position, either because we became blocked,
or because we had to move off the path to avoid other units. */
virtual Path *patchPath( const Object *obj, const LocomotorSet& locomotorSet,
Path *originalPath, Bool blocked ) = 0;
/** Find a short, valid path to a location that is away from the repulsors. */
virtual Path *findSafePath( const Object *obj, const LocomotorSet& locomotorSet,
const Coord3D *from, const Coord3D* repulsorPos1, const Coord3D* repulsorPos2, Real repulsorRadius ) = 0;
};
/**
* The Pathfinding engine itself.
*/
class Pathfinder : PathfindServicesInterface, public Snapshot
{
// The following routines are private, but available through the doPathfind callback to aiInterface. jba.
private:
virtual Path *findPath( Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to); ///< Find a short, valid path between given locations
/** Find a short, valid path to a location NEAR the to location.
This succeds when the destination is unreachable (like inside a building).
If the destination is unreachable, it will adjust the to point. */
virtual Path *findClosestPath( Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from,
Coord3D *to, Bool blocked, Real pathCostMultiplier, Bool moveAllies );
/** Find a short, valid path to a location that obj can attack victim from. */
virtual Path *findAttackPath( const Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from,
const Object *victim, const Coord3D* victimPos, const Weapon *weapon );
/** Find a short, valid path to a location that is away from the repulsors. */
virtual Path *findSafePath( const Object *obj, const LocomotorSet& locomotorSet,
const Coord3D *from, const Coord3D* repulsorPos1, const Coord3D* repulsorPos2, Real repulsorRadius );
/** Patch to the exiting path from the current position, either because we became blocked,
or because we had to move off the path to avoid other units. */
virtual Path *patchPath( const Object *obj, const LocomotorSet& locomotorSet,
Path *originalPath, Bool blocked );
public:
Pathfinder( void );
~Pathfinder() ;
void reset( void ); ///< Reset system in preparation for new map
// --------------- inherited from Snapshot interface --------------
void crc( Xfer *xfer );
void xfer( Xfer *xfer );
void loadPostProcess( void );
Bool clientSafeQuickDoesPathExist( const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to ); ///< Can we build any path at all between the locations (terrain & buildings check - fast)
Bool clientSafeQuickDoesPathExistForUI( const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to ); ///< Can we build any path at all between the locations (terrain onlyk - fast)
Bool slowDoesPathExist( Object *obj, const Coord3D *from,
const Coord3D *to, ObjectID ignoreObject=INVALID_ID ); ///< Can we build any path at all between the locations (terrain, buildings & units check - slower)
Bool queueForPath(ObjectID id); ///< The object wants to request a pathfind, so put it on the list to process.
void processPathfindQueue(void); ///< Process some or all of the queued pathfinds.
void forceMapRecalculation( ); ///< Force pathfind map recomputation. If region is given, only that area is recomputed
/** Returns an aircraft path to the goal. */
Path *getAircraftPath( const Object *obj, const Coord3D *to);
Path *findGroundPath( const Coord3D *from, const Coord3D *to, Int pathRadius,
Bool crusher); ///< Find a short, valid path of the desired width on the ground.
void addObjectToPathfindMap( class Object *obj ); ///< Classify the given object's cells in the map
void removeObjectFromPathfindMap( class Object *obj ); ///< De-classify the given object's cells in the map
void removeUnitFromPathfindMap( Object *obj ); ///< De-classify the given mobile unit's cells in the map
void updateGoal( Object *obj, const Coord3D *newGoalPos, PathfindLayerEnum layer); ///< Update the given mobile unit's cells in the map
void updateAircraftGoal( Object *obj, const Coord3D *newGoalPos); ///< Update the given aircraft unit's cells in the map
void removeGoal( Object *obj); ///< Removes the given mobile unit's goal cells in the map
void updatePos( Object *obj, const Coord3D *newPos); ///< Update the given mobile unit's cells in the map
void removePos( Object *obj); ///< Removes the unit's position cells from the map
Bool moveAllies(Object *obj, Path *path);
// NOTE - The object MUST NOT MOVE between the call to createAWall... and removeWall...
// or BAD THINGS will happen. jba.
void createAWallFromMyFootprint( Object *obj ) {internal_classifyObjectFootprint(obj, true);} // Temporarily treat this object as an obstacle.
void removeWallFromMyFootprint( Object *obj ){internal_classifyObjectFootprint(obj, false);} // Undo createAWallFromMyFootprint.
Path *getMoveAwayFromPath(Object *obj, Object *otherObj, Path *pathToAvoid, Object *otherObj2, Path *pathToAvoid2);
void changeBridgeState( PathfindLayerEnum layer, Bool repaired );
Bool findBrokenBridge(const LocomotorSet &locomotorSet, const Coord3D *from, const Coord3D *to, ObjectID *bridgeID);
void newMap(void);
PathfindCell *getCell( PathfindLayerEnum layer, Int x, Int y ); ///< Return the cell at grid coords (x,y)
PathfindCell *getCell( PathfindLayerEnum layer, const Coord3D *pos ); ///< Given a position, return associated grid cell
PathfindCell *getClippedCell( PathfindLayerEnum layer, const Coord3D *pos ); ///< Given a position, return associated grid cell
void clip(Coord3D *from, Coord3D *to);
Bool worldToCell( const Coord3D *pos, ICoord2D *cell ); ///< Given a world position, return grid cell coordinate
const ICoord2D *getExtent(void) const {return &m_extent.hi;}
void setIgnoreObstacleID( ObjectID objID ); ///< if non-zero, the pathfinder will ignore the given obstacle
Bool validMovementPosition( Bool isCrusher, LocomotorSurfaceTypeMask acceptableSurfaces, PathfindCell *toCell, PathfindCell *fromCell = NULL ); ///< Return true if given position is a valid movement location
Bool validMovementPosition( Bool isCrusher, PathfindLayerEnum layer, const LocomotorSet& locomotorSet, Int x, Int y ); ///< Return true if given position is a valid movement location
Bool validMovementPosition( Bool isCrusher, PathfindLayerEnum layer, const LocomotorSet& locomotorSet, const Coord3D *pos ); ///< Return true if given position is a valid movement location
Bool validMovementTerrain( PathfindLayerEnum layer, const Locomotor* locomotor, const Coord3D *pos ); ///< Return true if given position is a valid movement location
Locomotor* chooseBestLocomotorForPosition(PathfindLayerEnum layer, LocomotorSet* locomotorSet, const Coord3D* pos );
Bool isViewBlockedByObstacle(const Object* obj, const Object* objOther); ///< Return true if the straight line between the given points contains any obstacle, and thus blocks vision
Bool isAttackViewBlockedByObstacle(const Object* obj, const Coord3D& attackerPos, const Object* victim, const Coord3D& victimPos); ///< Return true if the straight line between the given points contains any obstacle, and thus blocks vision
Bool isLinePassable( const Object *obj, LocomotorSurfaceTypeMask acceptableSurfaces,
PathfindLayerEnum layer, const Coord3D& startWorld, const Coord3D& endWorld,
Bool blocked, Bool allowPinched ); ///< Return true if the straight line between the given points is passable
void moveAlliesAwayFromDestination( Object *obj,const Coord3D& destination);
Bool isGroundPathPassable( Bool isCrusher, const Coord3D& startWorld, PathfindLayerEnum startLayer,
const Coord3D& endWorld, Int pathDiameter); ///< Return true if the straight line between the given points is passable
// for debugging
const Coord3D *getDebugPathPosition( void );
void setDebugPathPosition( const Coord3D *pos );
Path *getDebugPath( void );
void setDebugPath( Path *debugpath );
void cleanOpenAndClosedLists(void);
// Adjusts the destination to a spot near dest that is not occupied by other units.
Bool adjustDestination(Object *obj, const LocomotorSet& locomotorSet,
Coord3D *dest, const Coord3D *groupDest=NULL);
// Adjusts the destination to a spot near dest for landing that is not occupied by other units.
Bool adjustToLandingDestination(Object *obj, Coord3D *dest);
// Adjusts the destination to a spot that can attack target that is not occupied by other units.
Bool adjustTargetDestination(const Object *obj, const Object *target, const Coord3D *targetPos,
const Weapon *weapon, Coord3D *dest);
// Adjusts destination to a spot near dest that is possible to path to.
Bool adjustToPossibleDestination(Object *obj, const LocomotorSet& locomotorSet, Coord3D *dest);
void snapPosition(Object *obj, Coord3D *pos); // Snaps the current position to it's grid location.
void snapClosestGoalPosition(Object *obj, Coord3D *pos); // Snaps the current position to a good goal position.
Bool goalPosition(Object *obj, Coord3D *pos); // Returns the goal position on the grid.
PathfindLayerEnum addBridge(Bridge *theBridge); // Adds a bridge layer, and returns the layer id.
void addWallPiece(Object *wallPiece); // Adds a wall piece.
void removeWallPiece(Object *wallPiece); // Removes a wall piece.
Real getWallHeight(void) {return m_wallHeight;}
Bool isPointOnWall(const Coord3D *pos);
void updateLayer(Object *obj, PathfindLayerEnum layer); ///< Updates object's layer.
static void classifyMapCell( Int x, Int y, PathfindCell *cell); ///< Classify the given map cell
Int clearCellForDiameter( Bool crusher, Int cellX, Int cellY, PathfindLayerEnum layer, Int pathDiameter ); ///< Return true if given position is a valid movement location
protected:
virtual Path *internalFindPath( Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to); ///< Find a short, valid path between given locations
Path *findHierarchicalPath( Bool isHuman, const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to, Bool crusher);
Path *findClosestHierarchicalPath( Bool isHuman, const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to, Bool crusher);
Path *internal_findHierarchicalPath( Bool isHuman, const LocomotorSurfaceTypeMask locomotorSurface, const Coord3D *from, const Coord3D *to, Bool crusher, Bool closestOK);
void processHierarchicalCell( const ICoord2D &scanCell, const ICoord2D &deltaPathfindCell,
PathfindCell *parentCell,
PathfindCell *goalCell, zoneStorageType parentZone,
zoneStorageType *examinedZones, Int &numExZones,
Bool crusher, Int &cellCount);
Bool checkForAdjust(Object *, const LocomotorSet& locomotorSet, Bool isHuman, Int cellX, Int cellY,
PathfindLayerEnum layer, Int iRadius, Bool center,Coord3D *dest, const Coord3D *groupDest) ;
Bool checkForLanding(Int cellX, Int cellY,
PathfindLayerEnum layer, Int iRadius, Bool center,Coord3D *dest) ;
Bool checkForTarget(const Object *obj, Int cellX, Int cellY, const Weapon *weapon,
const Object *victim, const Coord3D *victimPos,
Int iRadius, Bool center,Coord3D *dest) ;
Bool checkForPossible(Bool isCrusher, Int fromZone, Bool center, const LocomotorSet& locomotorSet,
Int cellX, Int cellY, PathfindLayerEnum layer, Coord3D *dest, Bool startingInObstacle) ;
void getRadiusAndCenter(const Object *obj, Int &iRadius, Bool &center);
void adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D &pos, PathfindLayerEnum layer);
Bool checkDestination(const Object *obj, Int cellX, Int cellY, PathfindLayerEnum layer, Int iRadius, Bool centerInCell);
Bool checkForMovement(const Object *obj, TCheckMovementInfo &info);
Bool segmentIntersectsTallBuilding(const PathNode *curNode, PathNode *nextNode,
ObjectID ignoreBuilding, Coord3D *insertPos1, Coord3D *insertPos2, Coord3D *insertPos3); ///< Return true if the straight line between the given points intersects a tall building.
Bool circleClipsTallBuilding(const Coord3D *from, const Coord3D *to, Real radius, ObjectID ignoreBuilding, Coord3D *adjustTo); ///< Return true if the circle at the end of the line between the given points intersects a tall building.
enum {NO_ATTACK=0};
Int examineNeighboringCells(PathfindCell *parentCell, PathfindCell *goalCell,
const LocomotorSet& locomotorSet, Bool isHumanPlayer,
Bool centerInCell, Int radius, const ICoord2D &startCellNdx,
const Object *obj, Int attackDistance);
Bool pathDestination( Object *obj, const LocomotorSet& locomotorSet, Coord3D *dest,
PathfindLayerEnum layer, const Coord3D *groupDest); ///< Checks cost between given locations
Int checkPathCost(Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from,
const Coord3D *to);
void tightenPath(Object *obj, const LocomotorSet& locomotorSet, Coord3D *from,
const Coord3D *to);
/**
return 0 to continue iterating the line, nonzero to terminate the iteration.
the nonzero result will be returned as the result of iterateCellsAlongLine().
iterateCellsAlongLine will return zero if it completes.
*/
typedef Int (*CellAlongLineProc)(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
Int iterateCellsAlongLine(const Coord3D& startWorld, const Coord3D& endWorld,
PathfindLayerEnum layer, CellAlongLineProc proc, void* userData);
Int iterateCellsAlongLine(const ICoord2D &start, const ICoord2D &end,
PathfindLayerEnum layer, CellAlongLineProc proc, void* userData);
static Int linePassableCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
static Int groundPathPassableCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
static Int lineBlockedByObstacleCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
static Int tightenPathCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
static Int attackBlockedByObstacleCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
static Int examineCellsCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
static Int groundCellsCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
static Int moveAlliesDestinationCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
static Int segmentIntersectsBuildingCallback(Pathfinder* pathfinder, PathfindCell* from, PathfindCell* to, Int to_x, Int to_y, void* userData);
void classifyMap( void ); ///< Classify all cells in grid as obstacles, etc
void classifyObjectFootprint( Object *obj, Bool insert ); /** Classify the cells under the given object
If 'insert' is true, object is being added
If 'insert' is false, object is being removed */
void internal_classifyObjectFootprint( Object *obj, Bool insert ); /** Classify the cells under the given object
If 'insert' is true, object is being added
If 'insert' is false, object is being removed */
void classifyFence( Object *obj, Bool insert ); /** Classify the cells under the given fence object. */
void classifyUnitFootprint( Object *obj, Bool insert, Bool remove, Bool update ); /** Classify the cells under the given object If 'insert' is true, object is being added */
/// Convert world coordinate to array index
void worldToGrid( const Coord3D *pos, ICoord2D *cellIndex );
Bool evaluateCell(PathfindCell* newCell, PathfindCell *parentCell,
const LocomotorSet& locomotorSet,
Bool centerInCell, Int radius,
const Object *obj, Int attackDistance);
Path *buildActualPath( const Object *obj, LocomotorSurfaceTypeMask acceptableSurfaces,
const Coord3D *fromPos, PathfindCell *goalCell, Bool center, Bool blocked ); ///< Work backwards from goal cell to construct final path
Path *buildGroundPath( Bool isCrusher,const Coord3D *fromPos, PathfindCell *goalCell,
Bool center, Int pathDiameter ); ///< Work backwards from goal cell to construct final path
Path *buildHierachicalPath( const Coord3D *fromPos, PathfindCell *goalCell); ///< Work backwards from goal cell to construct final path
void prependCells( Path *path, const Coord3D *fromPos,
PathfindCell *goalCell, Bool center ); ///< Add pathfind cells to a path.
void debugShowSearch( Bool pathFound ); ///< Show all cells touched in the last search
static LocomotorSurfaceTypeMask validLocomotorSurfacesForCellType(PathfindCell::CellType t);
void checkChangeLayers(PathfindCell *parentCell);
#if defined _DEBUG || defined _INTERNAL
void doDebugIcons(void) ;
#endif
private:
/// This uses WAY too much memory. Should at least be array of pointers to cells w/ many fewer cells
PathfindCell *m_blockOfMapCells; ///< Pathfinding map - contains iconic representation of the map
PathfindCell **m_map; ///< Pathfinding map indexes - contains matrix indexing into the map.
IRegion2D m_extent; ///< Grid extent limits
IRegion2D m_logicalExtent; ///< Logical grid extent limits
PathfindCell *m_openList; ///< Cells ready to be explored
PathfindCell *m_closedList; ///< Cells already explored
Bool m_isMapReady; ///< True if all cells of map have been classified
Bool m_isTunneling; ///< True if path started in an obstacle
Int m_frameToShowObstacles; ///< Time to redraw obstacles. For debug output.
Coord3D debugPathPos; ///< Used for visual debugging
Path *debugPath; ///< Used for visual debugging
ObjectID m_ignoreObstacleID; ///< Ignore the given obstacle
PathfindZoneManager m_zoneManager; ///< Handles the pathfind zones.
PathfindLayer m_layers[LAYER_LAST+1];
ObjectID m_wallPieces[MAX_WALL_PIECES];
Int m_numWallPieces;
Real m_wallHeight;
Int m_moveAlliesDepth;
// Pathfind queue
ObjectID m_queuedPathfindRequests[PATHFIND_QUEUE_LEN];
Int m_queuePRHead;
Int m_queuePRTail;
Int m_cumulativeCellsAllocated;
};
inline void Pathfinder::setIgnoreObstacleID( ObjectID objID )
{
m_ignoreObstacleID = objID;
}
inline void Pathfinder::worldToGrid( const Coord3D *pos, ICoord2D *cellIndex )
{
cellIndex->x = REAL_TO_INT(pos->x/PATHFIND_CELL_SIZE);
cellIndex->y = REAL_TO_INT(pos->y/PATHFIND_CELL_SIZE);
}
inline Bool Pathfinder::validMovementPosition( Bool isCrusher, PathfindLayerEnum layer, const LocomotorSet& locomotorSet, Int x, Int y )
{
return validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), getCell( layer, x, y ) );
}
inline Bool Pathfinder::validMovementPosition( Bool isCrusher, PathfindLayerEnum layer, const LocomotorSet& locomotorSet, const Coord3D *pos )
{
Int x = REAL_TO_INT(pos->x/PATHFIND_CELL_SIZE);
Int y = REAL_TO_INT(pos->y/PATHFIND_CELL_SIZE);
return validMovementPosition( isCrusher, layer, locomotorSet, x, y );
}
inline const Coord3D *Pathfinder::getDebugPathPosition( void )
{
return &debugPathPos;
}
inline void Pathfinder::setDebugPathPosition( const Coord3D *pos )
{
debugPathPos = *pos;
}
inline Path *Pathfinder::getDebugPath( void )
{
return debugPath;
}
inline void Pathfinder::addObjectToPathfindMap( class Object *obj )
{
classifyObjectFootprint( obj, true );
}
inline void Pathfinder::removeObjectFromPathfindMap( class Object *obj )
{
classifyObjectFootprint( obj, false );
}
inline PathfindCell *Pathfinder::getCell( PathfindLayerEnum layer, Int x, Int y )
{
if (x >= m_extent.lo.x && x <= m_extent.hi.x &&
y >= m_extent.lo.y && y <= m_extent.hi.y)
{
PathfindCell *cell = NULL;
if (layer > LAYER_GROUND && layer <= LAYER_LAST)
{
cell = m_layers[layer].getCell(x, y);
if (cell)
return cell;
}
return &m_map[x][y];
}
else
{
return NULL;
}
}
inline PathfindCell *Pathfinder::getCell( PathfindLayerEnum layer, const Coord3D *pos )
{
ICoord2D cell;
Bool overflow = worldToCell( pos, &cell );
if (overflow) return NULL;
return getCell( layer, cell.x, cell.y );
}
inline PathfindCell *Pathfinder::getClippedCell( PathfindLayerEnum layer, const Coord3D *pos)
{
ICoord2D cell;
worldToCell( pos, &cell );
return getCell( layer, cell.x, cell.y );
}
inline Bool Pathfinder::worldToCell( const Coord3D *pos, ICoord2D *cell )
{
cell->x = REAL_TO_INT_FLOOR(pos->x/PATHFIND_CELL_SIZE);
cell->y = REAL_TO_INT_FLOOR(pos->y/PATHFIND_CELL_SIZE);
Bool overflow = false;
if (cell->x < m_extent.lo.x) {overflow = true; cell->x = m_extent.lo.x;}
if (cell->y < m_extent.lo.y) {overflow = true; cell->y = m_extent.lo.y;}
if (cell->x > m_extent.hi.x) {overflow = true; cell->x = m_extent.hi.x;}
if (cell->y > m_extent.hi.y) {overflow = true; cell->y = m_extent.hi.y;}
return overflow;
}
/**
* Return true if the given object ID is registered as an obstacle in this cell
*/
inline Bool PathfindCell::isObstaclePresent( ObjectID objID ) const
{
if (objID != INVALID_ID && (getType() == PathfindCell::CELL_OBSTACLE))
{
DEBUG_ASSERTCRASH(m_info, ("Should have info to be obstacle."));
return (m_info && m_info->m_obstacleID == objID);
}
return false;
}
#endif // _PATHFIND_H_

View file

@ -0,0 +1,304 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// AIPlayer.h
// Computerized opponent
// Author: Michael S. Booth, January 2002
#pragma once
#ifndef _AI_PLAYER_H_
#define _AI_PLAYER_H_
#include "Common/GameMemory.h"
#include "Common/Snapshot.h"
enum { INVALID_SKILLSET_SELECTION = -1 };
class BuildListInfo;
/**
* When a team is selected for training, a list of these
* "work orders" are created, one for each member of the team.
* This pairs team members with production buildings to keep
* track of who is building what, and allows us to track if
* a building was destroyed while in the process of training a unit.
*/
class WorkOrder : public MemoryPoolObject,
public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( WorkOrder, "WorkOrder" )
public:
WorkOrder():m_thing(NULL), m_factoryID(INVALID_ID), m_isResourceGatherer(false), m_numCompleted(0), m_numRequired(1), m_next(NULL) {};
Bool isWaitingToBuild( void ); ///< return true if nothing is yet building this unit
void validateFactory( Player *thisPlayer ); ///< verify factoryID still refers to an active object
public:
const ThingTemplate *m_thing; ///< thing to build
ObjectID m_factoryID; ///< ID of object that is building this, or zero if no-one is
WorkOrder *m_next;
Int m_numCompleted; ///< Number built.
Int m_numRequired; ///< Number needed.
Bool m_required; ///< True if part of minimum requirement.
Bool m_isResourceGatherer; ///< True if resource gatherer.
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
};
inline Bool WorkOrder::isWaitingToBuild( void )
{
if (m_factoryID!=INVALID_ID)
return false;
if (m_numCompleted >= m_numRequired)
return false;
return true;
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class TeamInQueue : public MemoryPoolObject,
public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( TeamInQueue, "TeamInQueue" )
private:
MAKE_DLINK(TeamInQueue, TeamBuildQueue) ///< the instances of our prototype
MAKE_DLINK(TeamInQueue, TeamReadyQueue) ///< the instances of our prototype
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
public:
TeamInQueue() :
m_workOrders(NULL),
m_team(NULL),
m_nextTeamInQueue(NULL),
m_sentToStartLocation(false),
m_reinforcement(false),
m_stopQueueing(false),
m_reinforcementID(INVALID_ID),
//Added By Sadullah Nader
//Initialization(s) inserted
m_frameStarted(0),
m_priorityBuild(FALSE)
//
{
}
Bool isAllBuilt( void ); ///< Returns true if the team is finished building.
Bool isBuildTimeExpired( void );///< Returns true if the team has run out of build time.
Bool isMinimumBuilt( void ); ///< Returns true if the team has started building at least the minimum number of units.
Bool includesADozer( void ); ///< Returns true if the team includes a dozer unit.
Bool areBuildsComplete( void ); ///< Returns true if all units in factories have finished building.
void disband( void ); ///< Disbands the team (moves units into the default team).
void stopQueueing(void) {m_stopQueueing=true;} ///< Stops building new units, just finishes current.
public:
WorkOrder *m_workOrders; ///< list of work orders
Bool m_priorityBuild; ///< True if the team is specifically requested.
Team *m_team; ///< the team that units built by the m_workOrders go into
TeamInQueue *m_nextTeamInQueue; ///< next
Int m_frameStarted; ///< Frame we started building.
Bool m_sentToStartLocation; ///< Has it been sent to it's start location?
Bool m_stopQueueing; ///< True if we are to quit queueing units (usually because we ran out of build time.)
Bool m_reinforcement; ///< True if it is a unit to reinforce an existing team.
ObjectID m_reinforcementID; ///< True if it is a unit to reinforce an existing team.
};
/**
* The computer-controlled opponent.
*/
class AIPlayer : public MemoryPoolObject,
public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AIPlayer, "AIPlayer" )
public:
AIPlayer( Player *p ); ///< constructor
virtual Bool computeSuperweaponTarget(const SpecialPowerTemplate *power, Coord3D *pos, Int playerNdx, Real weaponRadius); ///< Calculates best pos for weapon given radius.
public: // AIPlayer interface, may be overridden by AISkirmishPlayer. jba.
virtual void update(); ///< simulates the behavior of a player
virtual void newMap(); ///< New map loaded call.
/// Invoked when a unit I am training comes into existence
virtual void onUnitProduced( Object *factory, Object *unit );
/// Invoked when a structure I am building comes into existence
virtual void onStructureProduced( Object *factory, Object *structure );
virtual void buildSpecificAITeam(TeamPrototype *teamProto, Bool priorityBuild); ///< Builds this team immediately.
virtual void buildAIBaseDefense(Bool flank); ///< Builds base defense on front or flank of base.
virtual void buildAIBaseDefenseStructure(const AsciiString &thingName, Bool flank); ///< Builds base defense on front or flank of base.
virtual void buildSpecificAIBuilding(const AsciiString &thingName); ///< Builds this building as soon as possible.
virtual void recruitSpecificAITeam(TeamPrototype *teamProto, Real recruitRadius); ///< Builds this team immediately.
virtual Bool isSkirmishAI(void) {return false;}
virtual Player *getAiEnemy(void) {return NULL;} ///< Solo AI attacks based on scripting. Only skirmish auto-acquires an enemy at this point. jba.
virtual Bool checkBridges(Object *unit, Waypoint *way) {return false;}
virtual void repairStructure(ObjectID structure);
virtual void selectSkillset(Int skillset);
public:
Bool getBaseCenter(Coord3D *pos) const {*pos = m_baseCenter; return m_baseCenterSet;}
/// Difficulty level for this player.
GameDifficulty getAIDifficulty(void) const;
void setAIDifficulty(GameDifficulty difficulty) {m_difficulty = difficulty;}
void buildBySupplies(Int minimumCash, const AsciiString &thingName ); ///< Builds a building by supplies.
void buildSpecificBuildingNearestTeam( const AsciiString &thingName, const Team *team );
void buildUpgrade(const AsciiString &upgrade ); ///< Builds an upgrade.
/// A team is about to be destroyed.
void aiPreTeamDestroy( const Team *team );
/// Is the nearest supply source safe?
Bool isSupplySourceSafe( Int minSupplies );
/// Is a supply source attacked?
Bool isSupplySourceAttacked( void );
Bool isLocationSafe( const Coord3D *pos, const ThingTemplate *tthing);
/// Have the team guard a supply center.
void guardSupplyCenter( Team *team, Int minSupplies );
void setTeamDelaySeconds(Int delay) {m_teamSeconds = delay;}
/// Calculates the closest construction zone location based on a template.
Bool calcClosestConstructionZoneLocation( const ThingTemplate *constructTemplate, Coord3D *location );
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
virtual void doBaseBuilding(void);
virtual void checkReadyTeams(void);
virtual void checkQueuedTeams(void);
virtual void doTeamBuilding(void);
virtual void doUpgradesAndSkills(void);
virtual Object *findDozer(const Coord3D *pos);
virtual void queueDozer(void);
virtual Bool selectTeamToBuild( void ); ///< determine the next team to build
virtual Bool selectTeamToReinforce( Int minPriority ); ///< determine the next team to reinforce
virtual Bool startTraining( WorkOrder *order, Bool busyOK, AsciiString teamName); ///< find a production building that can handle the order, and start building
virtual Bool isAGoodIdeaToBuildTeam( TeamPrototype *proto ); ///< return true if team should be built
virtual void processBaseBuilding( void ); ///< do base-building behaviors
virtual void processTeamBuilding( void ); ///< do team-building behaviors
static Int getPlayerSuperweaponValue( Coord3D *center, Int playerNdx, Real radius, Bool includeMilitaryUnits = TRUE );
// End of aiplayer interface.
protected:
MAKE_DLINK_HEAD(TeamInQueue, TeamBuildQueue); ///< List of teams being build
MAKE_DLINK_HEAD(TeamInQueue, TeamReadyQueue); ///< List of teams built, waiting to reach rally point.
protected:
Bool isPossibleToBuildTeam( TeamPrototype *proto, Bool requireIdleFactory, Bool &needMoney ); ///< return true if team can be considered for building
Object *buildStructureNow(const ThingTemplate *bldgPlan, BuildListInfo *info ); ///< Build a base buiding.
Object *buildStructureWithDozer(const ThingTemplate *bldgPlan, BuildListInfo *info ); ///< Build a base buiding.
void clearTeamsInQueue( void ); ///< Delete all teams in the build queue.
void computeCenterAndRadiusOfBase(Coord3D *center, Real *radius);
Object *findFactory(const ThingTemplate *thing, Bool busyOK); ///< Find a factory to build a unit. If force is true, may return a busy factory.
void queueUnits( void ); ///< Check the team build list, & queue up units at any idle factories.
void checkForSupplyCenter( BuildListInfo *info, Object *bldg);
void queueSupplyTruck(void);
void updateBridgeRepair(void);
Bool dozerInQueue(void);
Object *findSupplyCenter(Int minSupplies);
static void getPlayerStructureBounds(Region2D *bounds, Int playerNdx, Bool conservative = FALSE );
protected:
Player *m_player; ///< the Player we represent
Bool m_readyToBuildTeam; ///< True if the team select timer has expired.
Bool m_readyToBuildStructure; ///< True if the buildDelay timer has expired.
Int m_teamTimer; ///< Counts out the time between teams, as specified by ini.
Int m_structureTimer; ///< Counts out the time between structures, as specified by ini.
Int m_teamSeconds; ///< How many seconds to delay between teams.
Int m_buildDelay; ///< Delay for building in case we are resource or prereq. limited.
Int m_teamDelay; ///< Delay for teams in case we are resource or factory prereq. limited.
Int m_frameLastBuildingBuilt; ///< When we built the last building.
GameDifficulty m_difficulty;
Int m_skillsetSelector;
Coord3D m_baseCenter; // Center of the initial build list of structures.
Bool m_baseCenterSet; // True if baseCenter is valid.
Real m_baseRadius; // Radius of the initial build list of structures.
// Bridge repair info.
enum {MAX_STRUCTURES_TO_REPAIR = 2};
ObjectID m_structuresToRepair[MAX_STRUCTURES_TO_REPAIR];
ObjectID m_repairDozer;
Coord3D m_repairDozerOrigin;
Int m_structuresInQueue;
Bool m_dozerQueuedForRepair;
Bool m_dozerIsRepairing; ///< the repair dozer is trying to repair the bridge.
Int m_bridgeTimer;
UnsignedInt m_supplySourceAttackCheckFrame;
ObjectID m_attackedSupplyCenter;
ObjectID m_curWarehouseID;
};
#endif // _AI_PLAYER_H_

View file

@ -0,0 +1,125 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// AISkirmishPlayer.h
// Computerized opponent
// Author: Michael S. Booth, January 2002
#pragma once
#ifndef _AI_SKIRMISH_PLAYER_H_
#define _AI_SKIRMISH_PLAYER_H_
#include "Common/GameMemory.h"
#include "GameLogic/AIPlayer.h"
class BuildListInfo;
class SpecialPowerTemplate;
/**
* The computer-controlled opponent.
*/
class AISkirmishPlayer : public AIPlayer
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AISkirmishPlayer, "AISkirmishPlayer" )
public: // AISkirmish specific methods.
AISkirmishPlayer( Player *p ); ///< constructor
virtual Bool computeSuperweaponTarget(const SpecialPowerTemplate *power, Coord3D *pos, Int playerNdx, Real weaponRadius); ///< Calculates best pos for weapon given radius.
public: // AIPlayer interface methods.
virtual void update(); ///< simulates the behavior of a player
virtual void newMap(); ///< New map loaded call.
/// Invoked when a unit I am training comes into existence
virtual void onUnitProduced( Object *factory, Object *unit );
virtual void buildSpecificAITeam(TeamPrototype *teamProto, Bool priorityBuild); ///< Builds this team immediately.
virtual void buildSpecificAIBuilding(const AsciiString &thingName); ///< Builds this building as soon as possible.
virtual void buildAIBaseDefense(Bool flank); ///< Builds base defense on front or flank of base.
virtual void buildAIBaseDefenseStructure(const AsciiString &thingName, Bool flank); ///< Builds base defense on front or flank of base.
virtual void recruitSpecificAITeam(TeamPrototype *teamProto, Real recruitRadius); ///< Builds this team immediately.
virtual Bool isSkirmishAI(void) {return true;}
virtual Bool checkBridges(Object *unit, Waypoint *way);
virtual Player *getAiEnemy(void); ///< Solo AI attacks based on scripting. Only skirmish auto-acquires an enemy at this point. jba.
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
virtual void doBaseBuilding(void);
virtual void checkReadyTeams(void);
virtual void checkQueuedTeams(void);
virtual void doTeamBuilding(void);
virtual Object *findDozer(const Coord3D *pos);
virtual void queueDozer(void);
protected:
virtual Bool selectTeamToBuild( void ); ///< determine the next team to build
virtual Bool selectTeamToReinforce( Int minPriority ); ///< determine the next team to reinforce
virtual Bool startTraining( WorkOrder *order, Bool busyOK, AsciiString teamName); ///< find a production building that can handle the order, and start building
virtual Bool isAGoodIdeaToBuildTeam( TeamPrototype *proto ); ///< return true if team should be built
virtual void processBaseBuilding( void ); ///< do base-building behaviors
virtual void processTeamBuilding( void ); ///< do team-building behaviors
protected:
void adjustBuildList(BuildListInfo *list);
Int getMyEnemyPlayerIndex(void);
void acquireEnemy(void);
protected:
Int m_curFrontBaseDefense; // First is 0.
Int m_curFlankBaseDefense; // First is 0.
Real m_curFrontLeftDefenseAngle;
Real m_curFrontRightDefenseAngle;
Real m_curLeftFlankLeftDefenseAngle;
Real m_curLeftFlankRightDefenseAngle;
Real m_curRightFlankLeftDefenseAngle;
Real m_curRightFlankRightDefenseAngle;
UnsignedInt m_frameToCheckEnemy;
Player *m_currentEnemy;
};
#endif // _AI_SKIRMISH_PLAYER_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,251 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AITNGuard.h
/*---------------------------------------------------------------------------*/
/* EA Pacific */
/* Confidential Information */
/* Copyright (C) 2001 - All Rights Reserved */
/* DO NOT DISTRIBUTE */
/*---------------------------------------------------------------------------*/
/* Project: RTS3 */
/* File name: AITNGuard.h */
/* Created: John K. McDonald, Jr., 3/29/2002 */
/* Desc: // Define Guard states for AI */
/* Revision History: */
/* 3/29/2002 : Initial creation */
/*---------------------------------------------------------------------------*/
#pragma once
#ifndef _H_AITNGUARD_
#define _H_AITNGUARD_
// INCLUDES ///////////////////////////////////////////////////////////////////
#include "Common/GameMemory.h"
#include "GameLogic/AIStateMachine.h"
#include "GameLogic/GameLogic.h"
#include "GameLogic/Object.h"
#include "GameLogic/AI.h"
// DEFINES ////////////////////////////////////////////////////////////////////
// TYPE DEFINES ///////////////////////////////////////////////////////////////
enum
{
// prevent collisions with other states that we might use, (namely AI_IDLE)
AI_TN_GUARD_INNER = 5000, ///< Attack anything within this area till death
AI_TN_GUARD_IDLE, ///< Wait till something shows up to attack.
AI_TN_GUARD_OUTER, ///< Attack anything within this area that has been aggressive, until the timer expires
AI_TN_GUARD_RETURN, ///< Restore to a position within the inner circle
AI_TN_GUARD_GET_CRATE, ///< Pick up a crate from an enemy we killed.
AI_TN_GUARD_ATTACK_AGGRESSOR, ///< Attack something that attacked me (that I can attack)
};
//--------------------------------------------------------------------------------------
class TunnelNetworkExitConditions : public AttackExitConditionsInterface
{
public:
UnsignedInt m_attackGiveUpFrame; // frame at which we give up (if using)
TunnelNetworkExitConditions() : m_attackGiveUpFrame(0)
{
}
virtual Bool shouldExit(const StateMachine* machine) const;
};
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------
class AITNGuardMachine : public StateMachine
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AITNGuardMachine, "AITNGuardMachinePool" );
private:
Coord3D m_positionToGuard;
ObjectID m_nemesisToAttack;
GuardMode m_guardMode;
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
public:
/**
* The implementation of this constructor defines the states
* used by this machine.
*/
AITNGuardMachine( Object *owner );
const Coord3D *getPositionToGuard( void ) const { return &m_positionToGuard; }
void setTargetPositionToGuard( const Coord3D *pos) { m_positionToGuard = *pos; }
void setNemesisID(ObjectID id) { m_nemesisToAttack = id; }
ObjectID getNemesisID() const { return m_nemesisToAttack; }
GuardMode getGuardMode() const { return m_guardMode; }
void setGuardMode(GuardMode guardMode) { m_guardMode = guardMode; }
Bool lookForInnerTarget(void);
static Real getStdGuardRange(const Object* obj);
};
//--------------------------------------------------------------------------------------
class AITNGuardInnerState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AITNGuardInnerState, "AITNGuardInnerState")
public:
AITNGuardInnerState( StateMachine *machine ) : State( machine, "AITNGuardInner" ) { }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AITNGuardMachine* getGuardMachine() { return (AITNGuardMachine*)getMachine(); }
TunnelNetworkExitConditions m_exitConditions;
Bool m_scanForEnemy;
AIAttackState *m_attackState;
};
EMPTY_DTOR(AITNGuardInnerState)
//--------------------------------------------------------------------------------------
class AITNGuardIdleState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AITNGuardIdleState, "AITNGuardIdleState")
public:
AITNGuardIdleState( StateMachine *machine ) : State( machine, "AITNGuardIdleState" ) { }
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AITNGuardMachine* getGuardMachine() { return (AITNGuardMachine*)getMachine(); }
UnsignedInt m_nextEnemyScanTime;
Coord3D m_guardeePos; ///< Where the object we are guarding was last.
};
EMPTY_DTOR(AITNGuardIdleState)
//--------------------------------------------------------------------------------------
class AITNGuardOuterState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AITNGuardOuterState, "AITNGuardOuterState")
public:
AITNGuardOuterState( StateMachine *machine ) : State( machine, "AITNGuardOuter" )
{
m_attackState = NULL;
}
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AITNGuardMachine* getGuardMachine() { return (AITNGuardMachine*)getMachine(); }
TunnelNetworkExitConditions m_exitConditions;
AIAttackState *m_attackState;
};
EMPTY_DTOR(AITNGuardOuterState)
//--------------------------------------------------------------------------------------
class AITNGuardReturnState : public AIEnterState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AITNGuardReturnState, "AITNGuardReturnState")
private:
AITNGuardMachine* getGuardMachine() { return (AITNGuardMachine*)getMachine(); }
public:
AITNGuardReturnState( StateMachine *machine ) : AIEnterState(machine )
{
m_nextReturnScanTime = 0;
}
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
UnsignedInt m_nextReturnScanTime;
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
};
EMPTY_DTOR(AITNGuardReturnState)
//--------------------------------------------------------------------------------------
class AITNGuardPickUpCrateState : public AIPickUpCrateState
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AITNGuardPickUpCrateState, "AITNGuardPickUpCrateState")
public:
AITNGuardPickUpCrateState( StateMachine *machine );
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
};
EMPTY_DTOR(AITNGuardPickUpCrateState)
//--------------------------------------------------------------------------------------
class AITNGuardAttackAggressorState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AITNGuardAttackAggressorState, "AITNGuardAttackAggressorState")
public:
AITNGuardAttackAggressorState( StateMachine *machine );
virtual StateReturnType onEnter( void );
virtual StateReturnType update( void );
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
AITNGuardMachine* getGuardMachine() { return (AITNGuardMachine*)getMachine(); }
TunnelNetworkExitConditions m_exitConditions;
AIAttackState *m_attackState;
};
EMPTY_DTOR(AITNGuardAttackAggressorState)
//--------------------------------------------------------------------------------------
#endif /* _H_AIGUARD_ */

View file

@ -0,0 +1,134 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Armor.h /////////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, March 2002
// Desc: Damage Multiplier Descriptions
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _Armor_H_
#define _Armor_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/NameKeyGenerator.h"
#include "Common/STLTypedefs.h"
#include "GameLogic/Damage.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class ArmorStore;
//-------------------------------------------------------------------------------------------------
/**
An Armor encapsulates the a particular type of actual modifier to damage taken, in order
to simulate different materials, and to help make game balance easier to adjust.
*/
//-------------------------------------------------------------------------------------------------
class ArmorTemplate
{
public:
ArmorTemplate();
void clear();
/**
This is the real "meat" of the class: given a damage type and amount, adjust the damage
and return the amount that should be dealt.
*/
Real adjustDamage(DamageType t, Real damage) const;
static void parseArmorCoefficients( INI* ini, void *instance, void* /* store */, const void* userData );
protected:
private:
Real m_damageCoefficient[DAMAGE_NUM_TYPES]; ///< modifiers to damage
};
//-------------------------------------------------------------------------------------------------
class Armor
{
public:
inline Armor(const ArmorTemplate* tmpl = NULL) : m_template(tmpl)
{
}
inline Real adjustDamage(DamageType t, Real damage) const
{
return m_template ? m_template->adjustDamage(t, damage) : damage;
}
inline void clear()
{
m_template = NULL;
}
private:
const ArmorTemplate* m_template; ///< the kind of armor this is
};
//------------------------------------------------------------------------------------------------
/** Interface class for TheArmorStore, which is just a convenient place for us to
* store each Armor we read from INI together in a list, with some access
* methods for finding Armors */
//-------------------------------------------------------------------------------------------------
class ArmorStore : public SubsystemInterface
{
public:
ArmorStore();
~ArmorStore();
void init() { }
void reset() { }
void update() { }
/**
Find the Armor with the given name. If no such Armor exists, return null.
*/
const ArmorTemplate* findArmorTemplate(AsciiString name) const;
inline Armor makeArmor(const ArmorTemplate *tmpl) const
{
return Armor(tmpl); // my, that was easy
}
static void parseArmorDefinition(INI* ini);
private:
typedef std::hash_map< NameKeyType, ArmorTemplate, rts::hash<NameKeyType>, rts::equal_to<NameKeyType> > ArmorTemplateMap;
ArmorTemplateMap m_armorTemplates;
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern ArmorStore *TheArmorStore;
#endif // _Armor_H_

View file

@ -0,0 +1,103 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// ArmorSet.h
#pragma once
#ifndef _ArmorSet_H_
#define _ArmorSet_H_
#include "Lib/BaseType.h"
#include "Common/GameType.h"
#include "Common/SparseMatchFinder.h"
#include "Common/SparseMatchFinder.h"
//-------------------------------------------------------------------------------------------------
class ArmorTemplate;
class DamageFX;
class INI;
//-------------------------------------------------------------------------------------------------
// IMPORTANT NOTE: you should endeavor to set up states such that the most "normal"
// state is defined by the bit being off. That is, the typical "normal" condition
// has all condition flags set to zero.
enum ArmorSetType
{
// The access and use of this enum has the bit shifting built in, so this is a 0,1,2,3,4,5 enum
ARMORSET_VETERAN = 0,
ARMORSET_ELITE = 1,
ARMORSET_HERO = 2,
ARMORSET_PLAYER_UPGRADE = 3,
ARMORSET_WEAK_VERSUS_BASEDEFENSES = 4,
ARMORSET_SECOND_LIFE = 5, ///< Body Module has marked us as on our second life
ARMORSET_CRATE_UPGRADE_ONE, ///< Just like weaponset type from salvage.
ARMORSET_CRATE_UPGRADE_TWO,
ARMORSET_COUNT ///< keep last, please
};
//-------------------------------------------------------------------------------------------------
typedef BitFlags<ARMORSET_COUNT> ArmorSetFlags;
//-------------------------------------------------------------------------------------------------
class ArmorTemplateSet
{
private:
ArmorSetFlags m_types;
const ArmorTemplate* m_template;
const DamageFX* m_fx;
public:
inline ArmorTemplateSet()
{
clear();
}
inline void clear()
{
m_types.clear();
m_template = NULL;
m_fx = NULL;
}
inline const ArmorTemplate* getArmorTemplate() const { return m_template; }
inline const DamageFX* getDamageFX() const { return m_fx; }
inline Int getConditionsYesCount() const { return 1; }
inline const ArmorSetFlags& getNthConditionsYes(Int i) const { return m_types; }
#if defined(_DEBUG) || defined(_INTERNAL)
inline AsciiString getDescription() const { return AsciiString("ArmorTemplateSet"); }
#endif
void parseArmorTemplateSet( INI* ini );
};
//-------------------------------------------------------------------------------------------------
typedef std::vector<ArmorTemplateSet> ArmorTemplateSetVector;
//-------------------------------------------------------------------------------------------------
typedef SparseMatchFinder<ArmorTemplateSet, ArmorSetFlags> ArmorTemplateSetFinder;
#endif // _ArmorSet_H_

View file

@ -0,0 +1,76 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CaveSystem.h /////////////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood July 2002
// Desc: System responsible for keeping track of the connectedness of all cave systems on the map
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef CAVE_SYSTEM_H
#define CAVE_SYSTEM_H
class Object;
class TunnelTracker; // The player owns one such object for his Tunnels, so instead of duplicating
// so much code, this SubSystem will manage all of the Cave systems.
#include "Common/Snapshot.h"
#include "Common/SubsystemInterface.h"
/**
System responsible for Crates as code objects - ini, new/delete etc
*/
class CaveSystem : public SubsystemInterface,
public Snapshot
{
public:
CaveSystem();
~CaveSystem();
void init();
void reset();
void update();
Bool canSwitchIndexToIndex( Int oldIndex, Int newIndex ); // If either Index has guys in it, no, you can't
void registerNewCave( Int theIndex ); // All Caves are born with a default index, which could be new
void unregisterCave( Int theIndex ); //
TunnelTracker *getTunnelTrackerForCaveIndex( Int theIndex );
protected:
// snapshot methods
virtual void crc( Xfer *xfer ) { }
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void ) { }
private:
std::vector<TunnelTracker*> m_tunnelTrackerVector;// A vector of pointers where the indexes are known by
// others, so it can have NULLs in it to keep position. I've been advised against a map, so don't be a jerk
// and use spot 20 first.
};
extern CaveSystem *TheCaveSystem;
#endif

View file

@ -0,0 +1,116 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CrateSystem.h /////////////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood Feb 2002
// Desc: System responsible for Crates as code objects - ini, new/delete etc
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef CRATE_SYSTEM_H
#define CRATE_SYSTEM_H
#include "Common/Ini.h"
#include "Common/Overridable.h"
#include "Common/Override.h"
enum ScienceType;
struct crateCreationEntry
{
AsciiString crateName;
Real crateChance;
};
typedef std::list< crateCreationEntry > crateCreationEntryList;
typedef std::list< crateCreationEntry >::iterator crateCreationEntryIterator;
typedef std::list< crateCreationEntry >::const_iterator crateCreationEntryConstIterator;
/**
A CrateTemplate is a ini defined set of conditions plus a ThingTemplate that is the Object
containing the correct CrateCollide module.
*/
class CrateTemplate : public Overridable
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CrateTemplate, "CrateTemplate" )
public:
CrateTemplate();
// virtual destructor declared by memory pool
void setName( AsciiString name ) { m_name = name; }
AsciiString getName(){ return m_name; }
inline const FieldParse *getFieldParse() const { return TheCrateTemplateFieldParseTable; }
static const FieldParse TheCrateTemplateFieldParseTable[]; ///< the parse table for INI definition
static void parseCrateCreationEntry( INI* ini, void *instance, void *store, const void* /*userData*/ );
AsciiString m_name; ///< name for this CrateTemplate
Real m_creationChance; ///< Condition for random percentage chance of creating
VeterancyLevel m_veterancyLevel; ///< Condition specifing level of killed unit
KindOfMaskType m_killedByTypeKindof; ///< Must be killed by something with all these bits set
ScienceType m_killerScience; ///< Must be killed by something posessing this science
crateCreationEntryList m_possibleCrates; ///< CreationChance is for this CrateData to succeed, this list controls one-of-n crates created on success
Bool m_isOwnedByMaker; ///< Design needs crates to be owned sometimes.
private:
};
typedef OVERRIDE<CrateTemplate> CrateTemplateOverride;
/**
System responsible for Crates as code objects - ini, new/delete etc
*/
class CrateSystem : public SubsystemInterface
{
public:
CrateSystem();
~CrateSystem();
void init();
void reset();
void update(){}
const CrateTemplate *findCrateTemplate(AsciiString name) const;
CrateTemplate *friend_findCrateTemplate(AsciiString name);
CrateTemplate *newCrateTemplate( AsciiString name );
CrateTemplate *newCrateTemplateOverride( CrateTemplate *crateToOverride );
static void parseCrateTemplateDefinition(INI* ini);
private:
std::vector<CrateTemplate *> m_crateTemplateVector;
};
extern CrateSystem *TheCrateSystem;
#endif

View file

@ -0,0 +1,376 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Damage.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, November 2001
// Desc: Damage description
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DAMAGE_H_
#define __DAMAGE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/BitFlags.h"
#include "Common/GameType.h"
#include "Common/ObjectStatusTypes.h" // Precompiled header anyway, no detangling possibility
#include "Common/Snapshot.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Object;
class INI;
class ThingTemplate;
//-------------------------------------------------------------------------------------------------
/** Damage types, keep this in sync with DamageTypeFlags::s_bitNameList[] */
//-------------------------------------------------------------------------------------------------
enum DamageType
{
DAMAGE_EXPLOSION = 0,
DAMAGE_CRUSH = 1,
DAMAGE_ARMOR_PIERCING = 2,
DAMAGE_SMALL_ARMS = 3,
DAMAGE_GATTLING = 4,
DAMAGE_RADIATION = 5,
DAMAGE_FLAME = 6,
DAMAGE_LASER = 7,
DAMAGE_SNIPER = 8,
DAMAGE_POISON = 9,
DAMAGE_HEALING = 10,
DAMAGE_UNRESISTABLE = 11, // this is for scripting to cause 'armorproof' damage
DAMAGE_WATER = 12,
DAMAGE_DEPLOY = 13, // for transports to deploy units and order them to all attack.
DAMAGE_SURRENDER = 14, // if something "dies" to surrender damage, they surrender.... duh!
DAMAGE_HACK = 15,
DAMAGE_KILLPILOT = 16, // special snipe attack that kills the pilot and renders a vehicle unmanned.
DAMAGE_PENALTY = 17, // from game penalty (you won't receive radar warnings BTW)
DAMAGE_FALLING = 18,
DAMAGE_MELEE = 19, // Blades, clubs...
DAMAGE_DISARM = 20, // "special" damage type used for disarming mines, bombs, etc (NOT for "disarming" an opponent!)
DAMAGE_HAZARD_CLEANUP = 21, // special damage type for cleaning up hazards like radiation or bio-poison.
DAMAGE_PARTICLE_BEAM = 22, // Incinerates virtually everything (insanely powerful orbital beam)
DAMAGE_TOPPLING = 23, // damage from getting toppled.
DAMAGE_INFANTRY_MISSILE = 24,
DAMAGE_AURORA_BOMB = 25,
DAMAGE_LAND_MINE = 26,
DAMAGE_JET_MISSILES = 27,
DAMAGE_STEALTHJET_MISSILES = 28,
DAMAGE_MOLOTOV_COCKTAIL = 29,
DAMAGE_COMANCHE_VULCAN = 30,
DAMAGE_SUBDUAL_MISSILE = 31, ///< Damage that does not kill you, but produces some special effect based on your Body Module. Seperate HP from normal damage.
DAMAGE_SUBDUAL_VEHICLE = 32,
DAMAGE_SUBDUAL_BUILDING = 33,
DAMAGE_SUBDUAL_UNRESISTABLE = 34,
DAMAGE_MICROWAVE = 35, ///< Radiation that only affects infantry
DAMAGE_KILL_GARRISONED = 36, ///< Kills Passengers up to the number specified in Damage
DAMAGE_STATUS = 37, ///< Damage that gives a status condition, not that does hitpoint damage
// Please note: There is a string array DamageTypeFlags::s_bitNameList[]
DAMAGE_NUM_TYPES // keep this last
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
typedef BitFlags<DAMAGE_NUM_TYPES> DamageTypeFlags;
inline Bool getDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
{
return flags.test(dt);
}
inline DamageTypeFlags setDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
{
flags.set(dt, TRUE);
return flags;
}
inline DamageTypeFlags clearDamageTypeFlag(DamageTypeFlags flags, DamageType dt)
{
flags.set(dt, FALSE);
return flags;
}
// Instead of checking against a single damage type, gather the question here so we can have more than one
inline Bool IsSubdualDamage( DamageType type )
{
switch( type )
{
case DAMAGE_SUBDUAL_MISSILE:
case DAMAGE_SUBDUAL_VEHICLE:
case DAMAGE_SUBDUAL_BUILDING:
case DAMAGE_SUBDUAL_UNRESISTABLE:
return TRUE;
}
return FALSE;
}
/// Does this type of damage go to internalChangeHealth?
inline Bool IsHealthDamagingDamage( DamageType type )
{
// The need for this function brought to you by "Have the guy with no game experience write the weapon code" Foundation.
// Health Damage should be one type of WeaponEffect. Thinking "Weapons can only do damage" is why AoE is boring.
switch( type )
{
case DAMAGE_STATUS:
case DAMAGE_SUBDUAL_MISSILE:
case DAMAGE_SUBDUAL_VEHICLE:
case DAMAGE_SUBDUAL_BUILDING:
case DAMAGE_SUBDUAL_UNRESISTABLE:
case DAMAGE_KILLPILOT:
case DAMAGE_KILL_GARRISONED:
return FALSE;
}
return TRUE;
}
inline void SET_ALL_DAMAGE_TYPE_BITS(DamageTypeFlags& m)
{
m.clear();
m.flip();
}
extern DamageTypeFlags DAMAGE_TYPE_FLAGS_NONE;
extern DamageTypeFlags DAMAGE_TYPE_FLAGS_ALL;
void initDamageTypeFlags();
//-------------------------------------------------------------------------------------------------
/** Death types, keep this in sync with TheDeathNames[] */
//-------------------------------------------------------------------------------------------------
enum DeathType
{
// note that these DELIBERATELY have (slightly) different names from the damage names,
// since there isn't necessarily a one-to-one correspondence. e.g., DEATH_BURNED
// can come from DAMAGE_FLAME but also from DAMAGE_PARTICLE_BEAM.
DEATH_NORMAL = 0,
DEATH_NONE = 1, ///< this is a "special case" that can't normally cause death
DEATH_CRUSHED = 2,
DEATH_BURNED = 3,
DEATH_EXPLODED = 4,
DEATH_POISONED = 5,
DEATH_TOPPLED = 6,
DEATH_FLOODED = 7,
DEATH_SUICIDED = 8,
DEATH_LASERED = 9,
DEATH_DETONATED = 10, /**< this is the "death" that occurs when a missile/warhead/etc detonates normally,
as opposed to being shot down, etc */
DEATH_SPLATTED = 11, /**< the death that results from DAMAGE_FALLING */
DEATH_POISONED_BETA = 12,
// these are the "extra" types for yet-to-be-defined stuff. Don't bother renaming or adding
// or removing these; they are reserved for modders :-)
DEATH_EXTRA_2 = 13,
DEATH_EXTRA_3 = 14,
DEATH_EXTRA_4 = 15,
DEATH_EXTRA_5 = 16,
DEATH_EXTRA_6 = 17,
DEATH_EXTRA_7 = 18,
DEATH_EXTRA_8 = 19,
DEATH_POISONED_GAMMA = 20,
DEATH_NUM_TYPES // keep this last
};
#ifdef DEFINE_DEATH_NAMES
static const char *TheDeathNames[] =
{
"NORMAL",
"NONE",
"CRUSHED",
"BURNED",
"EXPLODED",
"POISONED",
"TOPPLED",
"FLOODED",
"SUICIDED",
"LASERED",
"DETONATED",
"SPLATTED",
"POISONED_BETA",
"EXTRA_2",
"EXTRA_3",
"EXTRA_4",
"EXTRA_5",
"EXTRA_6",
"EXTRA_7",
"EXTRA_8",
"POISONED_GAMMA",
NULL
};
#endif // end DEFINE_DEATH_NAMES
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
typedef UnsignedInt DeathTypeFlags;
const DeathTypeFlags DEATH_TYPE_FLAGS_ALL = 0xffffffff;
const DeathTypeFlags DEATH_TYPE_FLAGS_NONE = 0x00000000;
inline Bool getDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
{
return (flags & (1UL << (dt - 1))) != 0;
}
inline DeathTypeFlags setDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
{
return (flags | (1UL << (dt - 1)));
}
inline DeathTypeFlags clearDeathTypeFlag(DeathTypeFlags flags, DeathType dt)
{
return (flags & ~(1UL << (dt - 1)));
}
//-------------------------------------------------------------------------------------------------
/** Damage info inputs */
//-------------------------------------------------------------------------------------------------
class DamageInfoInput : public Snapshot
{
public:
DamageInfoInput( void )
{
m_sourceID = INVALID_ID;
m_sourceTemplate = NULL;
m_sourcePlayerMask = 0;
m_damageType = DAMAGE_EXPLOSION;
m_damageStatusType = OBJECT_STATUS_NONE;
m_damageFXOverride = DAMAGE_UNRESISTABLE;
m_deathType = DEATH_NORMAL;
m_amount = 0;
m_kill = FALSE;
m_shockWaveVector.zero();
m_shockWaveAmount = 0.0f;
m_shockWaveRadius = 0.0f;
m_shockWaveTaperOff = 0.0f;
}
ObjectID m_sourceID; ///< source of the damage
const ThingTemplate *m_sourceTemplate; ///< source of the damage (the template).
PlayerMaskType m_sourcePlayerMask; ///< Player mask of m_sourceID.
DamageType m_damageType; ///< type of damage
ObjectStatusTypes m_damageStatusType; ///< If status damage, what type
DamageType m_damageFXOverride; ///< If not marked as the default of Unresistable, the damage type to use in doDamageFX instead of the real damamge type
DeathType m_deathType; ///< if this kills us, death type to be used
Real m_amount; ///< # value of how much damage to inflict
Bool m_kill; ///< will always cause object to die regardless of damage.
// These are used for damage causing shockwave, forcing units affected to be pushed around
Coord3D m_shockWaveVector; ///< This represents the incoming damage vector
Real m_shockWaveAmount; ///< This represents the amount of shockwave created by the damage. 0 = no shockwave, 1.0 = shockwave equal to damage.
Real m_shockWaveRadius; ///< This represents the effect radius of the shockwave.
Real m_shockWaveTaperOff; ///< This represents the taper off effect of the shockwave at the tip of the radius. 0.0 means shockwave is 0% at the radius edge.
protected:
// snapshot methods
virtual void crc( Xfer *xfer ) { }
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void ) { }
};
const Real HUGE_DAMAGE_AMOUNT = 999999.0f;
//-------------------------------------------------------------------------------------------------
/** Damage into outputs */
//-------------------------------------------------------------------------------------------------
class DamageInfoOutput : public Snapshot
{
public:
DamageInfoOutput( void )
{
m_actualDamageDealt = 0;
m_actualDamageClipped = 0;
m_noEffect = false;
}
/**
m_actualDamageDealt is the damage we tried to apply to object (after multipliers and such).
m_actualDamageClipped is the value of m_actualDamageDealt, but clipped to the max health remaining of the obj.
example:
a mammoth tank fires a round at a small tank, attempting 100 damage.
the small tank has a damage multiplier of 50%, meaning that only 50 damage is applied.
furthermore, the small tank has only 30 health remaining.
so: m_actualDamageDealt = 50, m_actualDamageClipped = 30.
this distinction is useful, since visual fx really wants to do the fx for "50 damage",
even though it was more than necessary to kill this object; game logic, on the other hand,
may want to know the "clipped" damage for ai purposes.
*/
Real m_actualDamageDealt;
Real m_actualDamageClipped; ///< (see comment for m_actualDamageDealt)
Bool m_noEffect; ///< if true, no damage was done at all (generally due to being InactiveBody)
protected:
// snapshot methods
virtual void crc( Xfer *xfer ) { }
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void ) { }
};
//-------------------------------------------------------------------------------------------------
/** DamageInfo is a descriptor of damage we're trying to inflict. The structure
* is divided up into two parts, inputs and outputs.
*
* INPUTS: You must provide valid values for these fields in order for damage
* calculation to correctly take place
* OUTPUT: Upon returning from damage issuing functions, the output fields
* will be filled with the results of the damage occurrence
*/
//-------------------------------------------------------------------------------------------------
class DamageInfo : public Snapshot
{
public:
DamageInfoInput in; ///< inputs for the damage info
DamageInfoOutput out; ///< results for the damage occurrence
protected:
virtual void crc( Xfer *xfer ) { }
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void ){ }
};
#endif // __DAMAGE_H_

View file

@ -0,0 +1,78 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ExperienceTracker.h //////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, February 2002
// Desc: Keeps track of experience points so Veterance levels can be gained
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef EXPERIENCE_TRACKER_H
#define EXPERIENCE_TRACKER_H
#include "Common/GameCommon.h"
#include "Common/GameType.h"
#include "Common/GameMemory.h"
#include "Common/Snapshot.h"
class Object;
class ExperienceTracker : public MemoryPoolObject, public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ExperienceTracker, "ExperienceTrackerPool" )
public:
ExperienceTracker(Object *parent);
VeterancyLevel getVeterancyLevel() const { return m_currentLevel; } ///< What level am I?
Int getExperienceValue( const Object* killer ) const; ///< How much do give for being killed
Int getCurrentExperience( void ) const { return m_currentExperience; }; ///< How much experience do I have at the moment?
Bool isTrainable() const; ///< Can I gain experience?
Bool isAcceptingExperiencePoints() const; ///< Either I am trainable, or I have a Sink set up
void setVeterancyLevel( VeterancyLevel newLevel, Bool provideFeedback = TRUE ); ///< Set Level to this
void setMinVeterancyLevel( VeterancyLevel newLevel ); ///< Set Level to AT LEAST this... if we are already >= this level, do nothing.
void addExperiencePoints( Int experienceGain, Bool canScaleForBonus = TRUE ); ///< Gain this many exp.
Bool gainExpForLevel(Int levelsToGain, Bool canScaleForBonus = TRUE ); ///< Gain enough exp to gain a level. return false if can't gain a level.
Bool canGainExpForLevel(Int levelsToGain) const; ///< return same value as gainExpForLevel, but don't change anything
void setExperienceAndLevel(Int experienceIn, Bool provideFeedback = TRUE );
void setExperienceSink( ObjectID sink ); ///< My experience actually goes to this person (loose couple)
Real getExperienceScalar() const { return m_experienceScalar; }
void setExperienceScalar( Real scalar ) { m_experienceScalar = scalar; }
// --------------- inherited from Snapshot interface --------------
void crc( Xfer *xfer );
void xfer( Xfer *xfer );
void loadPostProcess( void );
private:
Object* m_parent; ///< Object I am owned by
VeterancyLevel m_currentLevel; ///< Level of experience
Int m_currentExperience; ///< Number of experience points
ObjectID m_experienceSink; ///< ID of object I have pledged my experience point gains to
Real m_experienceScalar; ///< Scales any experience gained by this multiplier.
};
#endif

View file

@ -0,0 +1,42 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FPUControl.h /////////////////////////////////////////////////////////////////////////////
// Author: Matthew D. Campbell, June 2002
// Desc: Routines for controlling the FPU state
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FPUCONTROL_H__
#define __FPUCONTROL_H__
/**
* setFPMode sets the FPU internal precision and rounding mode. As DirectX is not guaranteed to
* leave the FPU in a good state, we must call this at the start of GameLogic::update() and
* anywhere that touches DirectX inside GameLogic loops (LoadScreen).
*/
void setFPMode( void );
#endif // __FPUCONTROL_H__

View file

@ -0,0 +1,96 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FiringTracker.h //////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, February 2002
// Desc: Keeps track of shots fired and people targeted for weapons that want a history of such a thing
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef FIRING_TRACKER_H
#define FIRING_TRACKER_H
#include "Common/GameType.h"
#include "Common/GameMemory.h"
#include "Common/AudioEventRTS.h"
#include "GameLogic/Module/UpdateModule.h"
class Object;
class Weapon;
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class FiringTrackerModuleData : public ModuleData
{
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class FiringTracker : public UpdateModule
{
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FiringTracker, FiringTrackerModuleData )
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(FiringTracker, "FiringTrackerPool" )
public:
FiringTracker(Thing *thing, const ModuleData *modData);
void shotFired(const Weapon* weaponFired, ObjectID victimID ); ///< Owner just fired this weapon at this Object
ObjectID getLastShotVictim() const { return m_victimID; } ///< get the last victim ID that was shot at
Int getNumConsecutiveShotsAtVictim( const Object *victim ) const;
/// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj)
virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; }
virtual UpdateSleepTime update(); ///< See if spin down is needed because we haven't shot in a while
protected:
/*
The firingtracker needs to have its update run after all "normal"
user update modules, so it redefines this. Please don't redefine this
for other modules without very careful deliberation. (srj)
*/
virtual SleepyUpdatePhase getUpdatePhase() const
{
return PHASE_FINAL;
}
private:
void speedUp(); ///< I've qualified for an increase in my Object flag status
void coolDown(); ///< I need to slow down because it has been too long since I fired.
UpdateSleepTime calcTimeToSleep();
private:
Int m_consecutiveShots; ///< How many times I have shot at the same thing
ObjectID m_victimID; ///< The thing I have shot so many times
UnsignedInt m_frameToStartCooldown; ///< This is the frame I should cool down at, and is pushed back every time a shot is fired
UnsignedInt m_frameToForceReload; ///< Even more than AutoReload, this means it will pre-emptively reload instead of event triggering a delay after the last shot
UnsignedInt m_frameToStopLoopingSound; ///< if sound is looping, frame to stop looping it (or zero if not looping)
AudioHandle m_audioHandle;
};
#endif

View file

@ -0,0 +1,432 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GameLogic.h //////////////////////////////////////////////////////////////////////////////
// GameLogic singleton class - defines interface to GameLogic methods and objects
// Author: Michael S. Booth, October 2000
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _GAME_LOGIC_H_
#define _GAME_LOGIC_H_
#include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
#include "Common/GameType.h"
#include "Common/Snapshot.h"
#include "Common/STLTypedefs.h"
#include "Common/ObjectStatusTypes.h"
#include "GameNetwork/NetworkDefs.h"
#include "Common/STLTypedefs.h"
#include "GameLogic/Module/UpdateModule.h" // needed for DIRECT_UPDATEMODULE_ACCESS
/*
At one time, we distinguished between sleepy and nonsleepy
update modules, and kept a separate list for each. however,
now that the bulk of update modules are sleepy, profiling shows
that there is no real advantage to having the separate list,
so to simplify the world, I am removing it. If ALLOW_NONSLEEPY_UPDATES
is still undefined when we ship, please just nuke all the undefed
code. (srj)
*/
#define NO_ALLOW_NONSLEEPY_UPDATES
// forward declarations
class AudioEventRTS;
class Object;
class Drawable;
class Player;
class ThingTemplate;
class Team;
class CommandList;
class GameMessage;
class LoadScreen;
class WindowLayout;
class TerrainLogic;
class GhostObjectManager;
class CommandButton;
enum BuildableStatus;
typedef const CommandButton* ConstCommandButtonPtr;
// What kind of game we're in.
enum
{
GAME_SINGLE_PLAYER,
GAME_LAN,
GAME_SKIRMISH,
GAME_REPLAY,
GAME_SHELL,
GAME_INTERNET,
GAME_NONE
};
enum
{
CRC_CACHED,
CRC_RECALC
};
/// Function pointers for use by GameLogic callback functions.
typedef void (*GameLogicFuncPtr)( Object *obj, void *userData );
//typedef std::hash_map<ObjectID, Object *, rts::hash<ObjectID>, rts::equal_to<ObjectID> > ObjectPtrHash;
//typedef ObjectPtrHash::const_iterator ObjectPtrIter;
typedef std::vector<Object*> ObjectPtrVector;
// ------------------------------------------------------------------------------------------------
/**
* The implementation of GameLogic
*/
class GameLogic : public SubsystemInterface, public Snapshot
{
public:
GameLogic( void );
virtual ~GameLogic();
// subsytem methods
virtual void init( void ); ///< Initialize or re-initialize the instance
virtual void reset( void ); ///< Reset the logic system
virtual void update( void ); ///< update the world
#if defined(_DEBUG) || defined(_INTERNAL)
Int getNumberSleepyUpdates() const {return m_sleepyUpdates.size();} //For profiling, so not in Release.
#endif
void processCommandList( CommandList *list ); ///< process the command list
void prepareNewGame( Int gameMode, GameDifficulty diff, Int rankPoints ); ///< prepare for new game
void logicMessageDispatcher( GameMessage *msg,
void *userData ); ///< Logic command list processing
void registerObject( Object *obj ); ///< Given an object, register it with the GameLogic and give it a unique ID
void addObjectToLookupTable( Object *obj ); ///< add object ID to hash lookup table
void removeObjectFromLookupTable( Object *obj );///< remove object ID from hash lookup table
/// @todo Change this to refer to a Region3D as an extent of the world
void setWidth( Real width ); ///< Sets the width of the world
Real getWidth( void ); ///< Returns the width of the world
void setHeight( Real height ); ///< Sets the height of the world
Real getHeight( void ); ///< Returns the height of the world
Bool isInGameLogicUpdate( void ) const { return m_isInUpdate; }
UnsignedInt getFrame( void ); ///< Returns the current simulation frame number
UnsignedInt getCRC( Int mode = CRC_CACHED, AsciiString deepCRCFileName = AsciiString::TheEmptyString ); ///< Returns the CRC
void setObjectIDCounter( ObjectID nextObjID ) { m_nextObjID = nextObjID; }
ObjectID getObjectIDCounter( void ) { return m_nextObjID; }
//-----------------------------------------------------------------------------------------------
void setBuildableStatusOverride(const ThingTemplate* tt, BuildableStatus bs);
Bool findBuildableStatusOverride(const ThingTemplate* tt, BuildableStatus& bs) const;
void setControlBarOverride(const AsciiString& commandSetName, Int slot, ConstCommandButtonPtr commandButton);
Bool findControlBarOverride(const AsciiString& commandSetName, Int slot, ConstCommandButtonPtr& commandButton) const;
//-----------------------------------------------------------------------------------------------
/// create an object given the thing template. (Only for use by ThingFactory.)
Object *friend_createObject( const ThingTemplate *thing, const ObjectStatusMaskType &objectStatusMask, Team *team );
void destroyObject( Object *obj ); ///< Mark object as destroyed for later deletion
Object *findObjectByID( ObjectID id ); ///< Given an ObjectID, return a pointer to the object.
Object *getFirstObject( void ); ///< Returns the "first" object in the world. When used with the object method "getNextObject()", all objects in the world can be iterated.
ObjectID allocateObjectID( void ); ///< Returns a new unique object id
// super hack
void startNewGame( Bool loadSaveGame );
void loadMapINI( AsciiString mapName );
void updateLoadProgress( Int progress );
void deleteLoadScreen( void );
//Kris: Cut setGameLoading() and replaced with setLoadingMap() and setLoadingSave() -- reason: nomenclature
//void setGameLoading( Bool loading ) { m_loadingScene = loading; }
void setLoadingMap( Bool loading ) { m_loadingMap = loading; }
void setLoadingSave( Bool loading ) { m_loadingSave = loading; }
void setClearingGameData( Bool clearing ) { m_clearingGameData = clearing; }
void setGameMode( Int mode );
Int getGameMode( void );
Bool isInGame( void );
Bool isInLanGame( void );
Bool isInSinglePlayerGame( void );
Bool isInSkirmishGame( void );
Bool isInReplayGame( void );
Bool isInInternetGame( void );
Bool isInShellGame( void );
Bool isInMultiplayerGame( void );
//Kris: Cut isLoadingGame() and replaced with isLoadingMap() and isLoadingSave() -- reason: nomenclature
//Bool isLoadingGame() const { return m_loadingScene; } // This is the old function that isn't very clear on it's definition.
Bool isLoadingMap() const { return m_loadingMap; } // Whenever a map is in the process of loading.
Bool isLoadingSave() const { return m_loadingSave; } // Whenever a saved game is in the process of loading.
Bool isClearingGameData() const { return m_clearingGameData; }
void enableScoring(Bool score) { m_isScoringEnabled = score; }
Bool isScoringEnabled() const { return m_isScoringEnabled; }
void setShowBehindBuildingMarkers(Bool b) { m_showBehindBuildingMarkers = b; }
Bool getShowBehindBuildingMarkers() const { return m_showBehindBuildingMarkers; }
void setDrawIconUI(Bool b) { m_drawIconUI = b; }
Bool getDrawIconUI() const { return m_drawIconUI; }
void setShowDynamicLOD(Bool b) { m_showDynamicLOD = b; }
Bool getShowDynamicLOD() const { return m_showDynamicLOD; }
void setHulkMaxLifetimeOverride(Int b) { m_scriptHulkMaxLifetimeOverride = b; }
Int getHulkMaxLifetimeOverride() const { return m_scriptHulkMaxLifetimeOverride; }
Bool isIntroMoviePlaying();
void updateObjectsChangedTriggerAreas(void) {m_frameObjectsChangedTriggerAreas = m_frame;}
UnsignedInt getFrameObjectsChangedTriggerAreas(void) {return m_frameObjectsChangedTriggerAreas;}
void clearGameData(Bool showScoreScreen = TRUE); ///< Clear the game data
void closeWindows( void );
void sendObjectCreated( Object *obj );
void sendObjectDestroyed( Object *obj );
void bindObjectAndDrawable(Object* obj, Drawable* draw);
void setGamePaused( Bool paused, Bool pauseMusic = TRUE );
Bool isGamePaused( void );
Bool getInputEnabledMemory( void ) { return m_inputEnabledMemory; }
void processProgress(Int playerId, Int percentage);
void processProgressComplete(Int playerId);
Bool isProgressComplete( void );
void timeOutGameStart( void );
void initTimeOutValues( void );
UnsignedInt getObjectCount( void );
Int getRankLevelLimit() const { return m_rankLevelLimit; }
void setRankLevelLimit(Int limit)
{
if (limit < 1) limit = 1;
m_rankLevelLimit = limit;
}
// We need to allow access to this, because on a restartGame, we need to restart with the settings we started with
Int getRankPointsToAddAtGameStart() const { return m_rankPointsToAddAtGameStart; }
UnsignedShort getSuperweaponRestriction( void ) const; ///< Get any optional limits on superweapons
void setSuperweaponRestriction( void );
#ifdef DUMP_PERF_STATS
void getAIMetricsStatistics( UnsignedInt *numAI, UnsignedInt *numMoving, UnsignedInt *numAttacking, UnsignedInt *numWaitingForPath, UnsignedInt *overallFailedPathfinds );
void resetOverallFailedPathfinds() { m_overallFailedPathfinds = 0; }
void incrementOverallFailedPathfinds() { m_overallFailedPathfinds++; }
UnsignedInt getOverallFailedPathfinds() const { return m_overallFailedPathfinds; }
#endif
// NOTE: selectObject and deselectObject should be called *only* by logical things, NEVER by the
// client. These will cause the client to select or deselect the object, if affectClient is true.
// If createToSelection is TRUE, this object causes a new group to be selected.
void selectObject(Object *obj, Bool createNewSelection, PlayerMaskType playerMask, Bool affectClient = FALSE);
void deselectObject(Object *obj, PlayerMaskType playerMask, Bool affectClient = FALSE);
// this should be called only by UpdateModule, thanks.
void friend_awakenUpdateModule(Object* obj, UpdateModulePtr update, UnsignedInt whenToWakeUp);
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
void pushSleepyUpdate(UpdateModulePtr u);
UpdateModulePtr peekSleepyUpdate() const;
void popSleepyUpdate();
void eraseSleepyUpdate(Int i);
void rebalanceSleepyUpdate(Int i);
Int rebalanceParentSleepyUpdate(Int i);
Int rebalanceChildSleepyUpdate(Int i);
void remakeSleepyUpdate();
void validateSleepyUpdate() const;
private:
/**
overrides to thing template buildable status. doesn't really belong here,
but has to go somewhere. (srj)
*/
typedef std::hash_map< AsciiString, BuildableStatus, rts::hash<AsciiString>, rts::equal_to<AsciiString> > BuildableMap;
BuildableMap m_thingTemplateBuildableOverrides;
/**
overrides to control bars. doesn't really belong here, but has to go somewhere. (srj)
*/
typedef std::hash_map< AsciiString, ConstCommandButtonPtr, rts::hash<AsciiString>, rts::equal_to<AsciiString> > ControlBarOverrideMap;
ControlBarOverrideMap m_controlBarOverrides;
Real m_width, m_height; ///< Dimensions of the world
UnsignedInt m_frame; ///< Simulation frame number
// CRC cache system -----------------------------------------------------------------------------
UnsignedInt m_CRC; ///< Cache of previous CRC value
std::map<Int, UnsignedInt> m_cachedCRCs; ///< CRCs we've seen this frame
Bool m_shouldValidateCRCs; ///< Should we validate CRCs this frame?
//-----------------------------------------------------------------------------------------------
//Added By Sadullah Nader
//Used to for load scene
//Bool m_loadingScene;
Bool m_loadingMap;
Bool m_loadingSave;
Bool m_clearingGameData;
Bool m_isInUpdate;
Int m_rankPointsToAddAtGameStart;
Bool m_isScoringEnabled;
Bool m_showBehindBuildingMarkers; //used by designers to override the user setting for cinematics
Bool m_drawIconUI;
Bool m_showDynamicLOD; //used by designers to override the user setting for cinematics
Int m_scriptHulkMaxLifetimeOverride; ///< Scripts can change the lifetime of a hulk -- defaults to off (-1) in frames.
/// @todo remove this hack
Bool m_startNewGame;
WindowLayout *m_background;
Object* m_objList; ///< All of the objects in the world.
// ObjectPtrHash m_objHash; ///< Used for ObjectID lookups
ObjectPtrVector m_objVector;
// this is a vector, but is maintained as a priority queue.
// never modify it directly; please use the proper access methods.
// (for an excellent discussion of priority queues, please see:
// http://dogma.net/markn/articles/pq_stl/priority.htm)
std::vector<UpdateModulePtr> m_sleepyUpdates;
#ifdef ALLOW_NONSLEEPY_UPDATES
// this is a plain old list, not a pq.
std::list<UpdateModulePtr> m_normalUpdates;
#endif
UpdateModulePtr m_curUpdateModule;
ObjectPointerList m_objectsToDestroy; ///< List of things that need to be destroyed at end of frame
ObjectID m_nextObjID; ///< For allocating object id's
void setDefaults( Bool loadSaveGame ); ///< Set default values of class object
void processDestroyList( void ); ///< Destroy all pending objects on the destroy list
void destroyAllObjectsImmediate(); ///< destroy, and process destroy list immediately
/// factory for TheTerrainLogic, called from init()
virtual TerrainLogic *createTerrainLogic( void );
virtual GhostObjectManager *createGhostObjectManager(void);
Int m_gameMode;
Int m_rankLevelLimit;
UnsignedShort m_superweaponRestriction;
LoadScreen *getLoadScreen( Bool loadSaveGame );
LoadScreen *m_loadScreen;
Bool m_gamePaused;
Bool m_inputEnabledMemory;// Latches used to remember what to restore to after we unpause
Bool m_mouseVisibleMemory;
Bool m_progressComplete[MAX_SLOTS];
enum { PROGRESS_COMPLETE_TIMEOUT = 60000 }; ///< Timeout we wait for when we've completed our Load
Int m_progressCompleteTimeout[MAX_SLOTS];
void testTimeOut( void );
void lastHeardFrom( Int playerId );
Bool m_forceGameStartByTimeOut; ///< If we timeout someone we're waiting to load, set this flag to start the game
#ifdef DUMP_PERF_STATS
UnsignedInt m_overallFailedPathfinds;
#endif
UnsignedInt m_frameObjectsChangedTriggerAreas; ///< Last frame objects moved into/outof trigger areas, or were created/destroyed. jba.
// ----------------------------------------------------------------------------------------------
struct ObjectTOCEntry
{
AsciiString name;
UnsignedShort id;
};
typedef std::list< ObjectTOCEntry > ObjectTOCList;
typedef ObjectTOCList::iterator ObjectTOCListIterator;
ObjectTOCList m_objectTOC; ///< the object TOC
void addTOCEntry( AsciiString name, UnsignedShort id ); ///< add a new name/id TOC pair
ObjectTOCEntry *findTOCEntryByName( AsciiString name ); ///< find ObjectTOC by name
ObjectTOCEntry *findTOCEntryById( UnsignedShort id ); ///< find ObjectTOC by id
void xferObjectTOC( Xfer *xfer ); ///< save/load object TOC for current state of map
void prepareLogicForObjectLoad( void ); ///< prepare engine for object data from game file
};
// INLINE /////////////////////////////////////////////////////////////////////////////////////////
inline void GameLogic::setWidth( Real width ) { m_width = width; }
inline Real GameLogic::getWidth( void ) { return m_width; }
inline void GameLogic::setHeight( Real height ) { m_height = height; }
inline Real GameLogic::getHeight( void ) { return m_height; }
inline UnsignedInt GameLogic::getFrame( void ) { return m_frame; }
inline Bool GameLogic::isInGame( void ) { return !(m_gameMode == GAME_NONE); }
inline void GameLogic::setGameMode( Int mode ) { m_gameMode = mode; }
inline Int GameLogic::getGameMode( void ) { return m_gameMode; }
inline Bool GameLogic::isInLanGame( void ) { return (m_gameMode == GAME_LAN); }
inline Bool GameLogic::isInSkirmishGame( void ) { return (m_gameMode == GAME_SKIRMISH); }
inline Bool GameLogic::isInMultiplayerGame( void ) { return ((m_gameMode == GAME_LAN) || (m_gameMode == GAME_INTERNET)) ; }
inline Bool GameLogic::isInReplayGame( void ) { return (m_gameMode == GAME_REPLAY); }
inline Bool GameLogic::isInInternetGame( void ) { return (m_gameMode == GAME_INTERNET); }
inline Bool GameLogic::isInShellGame( void ) { return (m_gameMode == GAME_SHELL); }
inline UnsignedShort GameLogic::getSuperweaponRestriction() const { return m_superweaponRestriction; }
inline Object* GameLogic::findObjectByID( ObjectID id )
{
if( id == INVALID_ID )
return NULL;
// ObjectPtrHash::iterator it = m_objHash.find(id);
// if (it == m_objHash.end())
// return NULL;
//
// return (*it).second;
if( (Int)id < m_objVector.size() )
return m_objVector[(Int)id];
return NULL;
}
// the singleton
extern GameLogic *TheGameLogic;
#endif // _GAME_LOGIC_H_

View file

@ -0,0 +1,108 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GhostObject.h ////////////////////////////////////////////////////////////
// Placeholder for objects that have been deleted but need to be maintained because
// a player can see them fogged.
// Author: Mark Wilczynski, August 2002
#pragma once
#ifndef _GHOSTOBJECT_H_
#define _GHOSTOBJECT_H_
#include "Lib/BaseType.h"
#include "Common/Snapshot.h"
// #define DEBUG_FOG_MEMORY ///< this define is used to force object snapshots for all players, not just local player.
//Magic pointer value which indicates that a drawable pointer is actually invalid
//because we're looking at a ghost object.
#define GHOST_OBJECT_DRAWABLE 0xFFFFFFFF
class Object;
class PartitionData;
enum GeometryType;
enum ObjectID;
class GhostObject : public Snapshot
{
public:
GhostObject();
virtual ~GhostObject();
virtual void snapShot(int playerIndex)=0;
virtual void updateParentObject(Object *object, PartitionData *mod)=0;
virtual void freeSnapShot(int playerIndex)=0;
inline PartitionData *friend_getPartitionData(void) const {return m_partitionData;}
inline GeometryType getGeometryType(void) const {return m_parentGeometryType;}
inline Bool getGeometrySmall(void) const {return m_parentGeometryIsSmall;}
inline Real getGeometryMajorRadius(void) const {return m_parentGeometryMajorRadius;}
inline Real getGeometryMinorRadius(void) const {return m_parentGeometryminorRadius;}
inline Real getParentAngle(void) const {return m_parentAngle;}
inline const Coord3D *getParentPosition(void) const {return &m_parentPosition;}
protected:
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
Object *m_parentObject; ///< object which we are ghosting
GeometryType m_parentGeometryType;
Bool m_parentGeometryIsSmall;
Real m_parentGeometryMajorRadius;
Real m_parentGeometryminorRadius;
Real m_parentAngle;
Coord3D m_parentPosition;
PartitionData *m_partitionData; ///< our PartitionData
};
class GhostObjectManager : public Snapshot
{
public:
GhostObjectManager();
virtual ~GhostObjectManager();
virtual void reset(void);
virtual GhostObject *addGhostObject(Object *object, PartitionData *pd);
virtual void removeGhostObject(GhostObject *mod);
virtual inline void setLocalPlayerIndex(int index) { m_localPlayer = index; }
inline int getLocalPlayerIndex(void) { return m_localPlayer; }
virtual void updateOrphanedObjects(int *playerIndexList, int numNonLocalPlayers);
virtual void releasePartitionData(void); ///<saves data needed to later rebuild partition manager data.
virtual void restorePartitionData(void); ///<restores ghost objects into the partition manager.
inline void lockGhostObjects(Bool enableLock) {m_lockGhostObjects=enableLock;} ///<temporary lock on creating new ghost objects. Only used by map border resizing!
inline void saveLockGhostObjects(Bool enableLock) {m_saveLockGhostObjects=enableLock;}
protected:
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
Int m_localPlayer;
Bool m_lockGhostObjects;
Bool m_saveLockGhostObjects; ///< used to lock the ghost object system during a save/load
};
// the singleton
extern GhostObjectManager *TheGhostObjectManager;
#endif // _GAME_DISPLAY_H_

View file

@ -0,0 +1,510 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Locomotor.h /////////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, Feb 2002
// Desc: Locomotor Descriptions
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __Locomotor_H_
#define __Locomotor_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/NameKeyGenerator.h"
#include "Common/Override.h"
#include "Common/Snapshot.h"
#include "GameLogic/Damage.h"
#include "GameLogic/LocomotorSet.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Locomotor;
class LocomotorTemplate;
class INI;
class PhysicsBehavior;
enum BodyDamageType;
enum PhysicsTurningType;
// if we ever re-enable jets circling for landing, we need this. so keep in around just in case. (srj)
#define NO_CIRCLE_FOR_LANDING
//-------------------------------------------------------------------------------------------------
enum LocomotorAppearance
{
LOCO_LEGS_TWO,
LOCO_WHEELS_FOUR,
LOCO_TREADS,
LOCO_HOVER,
LOCO_THRUST,
LOCO_WINGS,
LOCO_CLIMBER, // human climber - backs down cliffs.
LOCO_OTHER,
LOCO_MOTORCYCLE
};
enum LocomotorPriority
{
LOCO_MOVES_BACK=0, // In a group, this one moves toward the back
LOCO_MOVES_MIDDLE=1, // In a group, this one stays in the middle
LOCO_MOVES_FRONT=2 // In a group, this one moves toward the front of the group
};
#ifdef DEFINE_LOCO_APPEARANCE_NAMES
static const char *TheLocomotorAppearanceNames[] =
{
"TWO_LEGS",
"FOUR_WHEELS",
"TREADS",
"HOVER",
"THRUST",
"WINGS",
"CLIMBER",
"OTHER",
"MOTORCYCLE",
NULL
};
#endif
//-------------------------------------------------------------------------------------------------
enum LocomotorBehaviorZ
{
Z_NO_Z_MOTIVE_FORCE, // does whatever physics tells it, but has no z-force of its own.
Z_SEA_LEVEL, // keep at surface-of-water level
Z_SURFACE_RELATIVE_HEIGHT, // try to follow a specific height relative to terrain/water height
Z_ABSOLUTE_HEIGHT, // try follow a specific height regardless of terrain/water height
Z_FIXED_SURFACE_RELATIVE_HEIGHT, // stays fixed at surface-rel height, regardless of physics
Z_FIXED_ABSOLUTE_HEIGHT, // stays fixed at absolute height, regardless of physics
Z_RELATIVE_TO_GROUND_AND_BUILDINGS, // stays fixed at surface-rel height including buildings, regardless of physics
Z_SMOOTH_RELATIVE_TO_HIGHEST_LAYER // try to follow a height relative to the highest layer.
};
#ifdef DEFINE_LOCO_Z_NAMES
static const char *TheLocomotorBehaviorZNames[] =
{
"NO_Z_MOTIVE_FORCE",
"SEA_LEVEL",
"SURFACE_RELATIVE_HEIGHT",
"ABSOLUTE_HEIGHT",
"FIXED_SURFACE_RELATIVE_HEIGHT",
"FIXED_ABSOLUTE_HEIGHT",
"FIXED_RELATIVE_TO_GROUND_AND_BUILDINGS",
"RELATIVE_TO_HIGHEST_LAYER",
NULL
};
#endif
//-------------------------------------------------------------------------------------------------
class LocomotorTemplate : public Overridable
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( LocomotorTemplate, "LocomotorTemplate" )
friend class Locomotor;
public:
LocomotorTemplate();
/// field table for loading the values from an INI
const FieldParse* getFieldParse() const;
void friend_setName(const AsciiString& n) { m_name = n; }
void validate();
protected:
private:
/**
Units check:
-- Velocity: dist/frame
-- Acceleration: dist/(frame*frame)
-- Forces: (mass*dist)/(frame*frame)
*/
AsciiString m_name;
LocomotorSurfaceTypeMask m_surfaces; ///< flags indicating the kinds of surfaces we can use
Real m_maxSpeed; ///< max speed
Real m_maxSpeedDamaged; ///< max speed when "damaged"
Real m_minSpeed; ///< we should never brake past this
Real m_maxTurnRate; ///< max rate at which we can turn, in rads/frame
Real m_maxTurnRateDamaged; ///< max turn rate when "damaged"
Real m_acceleration; ///< max acceleration
Real m_accelerationDamaged; ///< max acceleration when damaged
Real m_lift; ///< max lifting acceleration (flying objects only)
Real m_liftDamaged; ///< max lift when damaged
Real m_braking; ///< max braking (deceleration)
Real m_minTurnSpeed; ///< we must be going >= this speed in order to turn
Real m_preferredHeight; ///< our preferred height (if flying)
Real m_preferredHeightDamping; ///< how aggressively to adjust to preferred height: 1.0 = very much so, 0.1 = gradually, etc
Real m_circlingRadius; ///< for flying things, the radius at which they circle their "maintain" destination. (pos = cw, neg = ccw, 0 = smallest possible)
Real m_speedLimitZ; ///< try to avoid going up or down at more than this speed, if possible
Real m_extra2DFriction; ///< extra 2dfriction to apply (via Physics)
Real m_maxThrustAngle; ///< THRUST locos only: how much we deflect our thrust angle
LocomotorBehaviorZ m_behaviorZ; ///< z-axis behavior
LocomotorAppearance m_appearance; ///< how we should diddle the Drawable to imitate this motion
LocomotorPriority m_movePriority; ///< Where we move - front, middle, back.
Real m_accelPitchLimit; ///< Maximum amount we will pitch up under acceleration (including recoil.)
Real m_decelPitchLimit; ///< Maximum amount we will pitch down under deceleration (including recoil.)
Real m_bounceKick; ///< How much simulating rough terrain "bounces" a wheel up.
Real m_pitchStiffness; ///< How stiff the springs are forward & back.
Real m_rollStiffness; ///< How stiff the springs are side to side.
Real m_pitchDamping; ///< How good the shock absorbers are.
Real m_rollDamping; ///< How good the shock absorbers are.
Real m_pitchByZVelCoef; ///< How much we pitch in response to z-speed.
Real m_thrustRoll; ///< Thrust roll around X axis
Real m_wobbleRate; ///< how fast thrust things "wobble"
Real m_minWobble; ///< how much thrust things "wobble"
Real m_maxWobble; ///< how much thrust things "wobble"
Real m_forwardVelCoef; ///< How much we pitch in response to speed.
Real m_lateralVelCoef; ///< How much we roll in response to speed.
Real m_forwardAccelCoef; ///< How much we pitch in response to acceleration.
Real m_lateralAccelCoef; ///< How much we roll in response to acceleration.
Real m_uniformAxialDamping; ///< For Attenuating the pitch and roll rates
Real m_turnPivotOffset; ///< should we pivot around noncenter? (-1.0 = rear, 0.0 = center, 1.0 = front)
Int m_airborneTargetingHeight; ///< The height transition at witch I should mark myself as a AA target.
Real m_closeEnoughDist; ///< How close we have to approach the end of a path before stopping
Bool m_isCloseEnoughDist3D; ///< And is that calculation 3D, for very rare cases that need to move straight down.
Real m_ultraAccurateSlideIntoPlaceFactor; ///< how much we can fudge turning when ultra-accurate
Bool m_locomotorWorksWhenDead; ///< should locomotor continue working even when object is "dead"?
Bool m_allowMotiveForceWhileAirborne; ///< can we apply motive when airborne?
Bool m_apply2DFrictionWhenAirborne; // apply "2d friction" even when airborne... useful for realistic-looking movement
Bool m_downhillOnly; // pinewood derby, moves only by gravity pulling downhill
Bool m_stickToGround; // if true, can't leave ground
Bool m_canMoveBackward; // if true, can move backwards.
Bool m_hasSuspension; ///< If true, calculate 4 wheel independent suspension values.
Real m_maximumWheelExtension; ///< Maximum distance wheels can move down. (negative value)
Real m_maximumWheelCompression; ///< Maximum distance wheels can move up. (positive value)
Real m_wheelTurnAngle; ///< How far the front wheels can turn.
// Fields for wander locomotor
Real m_wanderWidthFactor;
Real m_wanderLengthFactor;
Real m_wanderAboutPointRadius;
Real m_rudderCorrectionDegree;
Real m_rudderCorrectionRate;
Real m_elevatorCorrectionDegree;
Real m_elevatorCorrectionRate;
};
typedef OVERRIDE<LocomotorTemplate> LocomotorTemplateOverride;
// ---------------------------------------------------------
class Locomotor : public MemoryPoolObject, public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Locomotor, "Locomotor" )
friend class LocomotorStore;
public:
void setPhysicsOptions(Object* obj);
void locoUpdate_moveTowardsPosition(Object* obj, const Coord3D& goalPos,
Real onPathDistToGoal, Real desiredSpeed, Bool *blocked);
void locoUpdate_moveTowardsAngle(Object* obj, Real angle);
/**
Kill any current (2D) velocity (but stay at current position, or as close as possible)
return true if we can maintain the position without being called every frame (eg, we are
resting on the ground), false if not (eg, we are hovering or circling)
*/
Bool locoUpdate_maintainCurrentPosition(Object* obj);
Real getMaxSpeedForCondition(BodyDamageType condition) const; ///< get max speed given condition
Real getMaxTurnRate(BodyDamageType condition) const; ///< get max turning rate given condition
Real getMaxAcceleration(BodyDamageType condition) const; ///< get acceleration given condition
Real getMaxLift(BodyDamageType condition) const; ///< get acceleration given condition
Real getBraking() const; ///< get braking given condition
inline Real getPreferredHeight() const { return m_preferredHeight;} ///< Just return preferredheight, no damage consideration
inline void restorePreferredHeightFromTemplate() { m_preferredHeight = m_template->m_preferredHeight; };
inline Real getPreferredHeightDamping() const { return m_preferredHeightDamping;}
inline LocomotorAppearance getAppearance() const { return m_template->m_appearance; }
inline LocomotorPriority getMovePriority() const { return m_template->m_movePriority; }
inline LocomotorSurfaceTypeMask getLegalSurfaces() const { return m_template->m_surfaces; }
inline AsciiString getTemplateName() const { return m_template->m_name;}
inline Real getMinSpeed() const { return m_template->m_minSpeed;}
inline Real getAccelPitchLimit() const { return m_template->m_accelPitchLimit;} ///< Maximum amount we will pitch up or down under acceleration (including recoil.)
inline Real getDecelPitchLimit() const { return m_template->m_decelPitchLimit;} ///< Maximum amount we will pitch down under deceleration (including recoil.)
inline Real getBounceKick() const { return m_template->m_bounceKick;} ///< How much simulating rough terrain "bounces" a wheel up.
inline Real getPitchStiffness() const { return m_template->m_pitchStiffness;} ///< How stiff the springs are forward & back.
inline Real getRollStiffness() const { return m_template->m_rollStiffness;} ///< How stiff the springs are side to side.
inline Real getPitchDamping() const { return m_template->m_pitchDamping;} ///< How good the shock absorbers are.
inline Real getRollDamping() const { return m_template->m_rollDamping;} ///< How good the shock absorbers are.
inline Real getPitchByZVelCoef() const { return m_template->m_pitchByZVelCoef;} ///< How much we pitch in response to speed.
inline Real getThrustRoll() const { return m_template->m_thrustRoll; } ///< Thrust roll
inline Real getWobbleRate() const { return m_template->m_wobbleRate; } ///< how fast thrust things "wobble"
inline Real getMaxWobble() const { return m_template->m_maxWobble; } ///< how much thrust things "wobble"
inline Real getMinWobble() const { return m_template->m_minWobble; } ///< how much thrust things "wobble"
inline Real getForwardVelCoef() const { return m_template->m_forwardVelCoef;} ///< How much we pitch in response to speed.
inline Real getLateralVelCoef() const { return m_template->m_lateralVelCoef;} ///< How much we roll in response to speed.
inline Real getForwardAccelCoef() const { return m_template->m_forwardAccelCoef;} ///< How much we pitch in response to acceleration.
inline Real getLateralAccelCoef() const { return m_template->m_lateralAccelCoef;} ///< How much we roll in response to acceleration.
inline Real getUniformAxialDamping() const { return m_template->m_uniformAxialDamping;} ///< How much we roll in response to acceleration.
inline Real getTurnPivotOffset() const { return m_template->m_turnPivotOffset;}
inline Bool getApply2DFrictionWhenAirborne() const { return m_template->m_apply2DFrictionWhenAirborne; }
inline Bool getIsDownhillOnly() const { return m_template->m_downhillOnly; }
inline Bool getAllowMotiveForceWhileAirborne() const { return m_template->m_allowMotiveForceWhileAirborne; }
inline Int getAirborneTargetingHeight() const { return m_template->m_airborneTargetingHeight; }
inline Bool getLocomotorWorksWhenDead() const { return m_template->m_locomotorWorksWhenDead; }
inline Bool getStickToGround() const { return m_template->m_stickToGround; }
inline Real getCloseEnoughDist() const { return m_closeEnoughDist; }
inline Bool isCloseEnoughDist3D() const { return getFlag(IS_CLOSE_ENOUGH_DIST_3D); }
inline Bool hasSuspension() const {return m_template->m_hasSuspension;}
inline Bool canMoveBackwards() const {return m_template->m_canMoveBackward;}
inline Real getMaxWheelExtension() const {return m_template->m_maximumWheelExtension;}
inline Real getMaxWheelCompression() const {return m_template->m_maximumWheelCompression;}
inline Real getWheelTurnAngle() const {return m_template->m_wheelTurnAngle;}
inline Real getRudderCorrectionDegree() const { return m_template->m_rudderCorrectionDegree;} ///< How much we roll in response to acceleration.
inline Real getRudderCorrectionRate() const { return m_template->m_rudderCorrectionRate;} ///< How much we roll in response to acceleration.
inline Real getElevatorCorrectionDegree() const { return m_template->m_elevatorCorrectionDegree;} ///< How much we roll in response to acceleration.
inline Real getElevatorCorrectionRate() const { return m_template->m_elevatorCorrectionRate;} ///< How much we roll in response to acceleration.
inline Real getWanderWidthFactor() const {return m_template->m_wanderWidthFactor;}
inline Real getWanderAboutPointRadius() const {return m_template->m_wanderAboutPointRadius;}
Real calcMinTurnRadius(BodyDamageType condition, Real* timeToTravelThatDist) const;
/// this is handy for doing things like forcing helicopters to crash realistically: cut their lift.
inline void setMaxLift(Real lift) { m_maxLift = lift; }
inline void setMaxSpeed(Real speed)
{
DEBUG_ASSERTCRASH(!(speed <= 0.0f && m_template->m_appearance == LOCO_THRUST), ("THRUST locos may not have zero speeds!\n"));
m_maxSpeed = speed;
}
inline void setMaxAcceleration(Real accel) { m_maxAccel = accel; }
inline void setMaxBraking(Real braking) { m_maxBraking = braking; }
inline void setMaxTurnRate(Real turn) { m_maxTurnRate = turn; }
inline void setAllowInvalidPosition(Bool allow) { setFlag(ALLOW_INVALID_POSITION, allow); }
inline void setCloseEnoughDist( Real dist ) { m_closeEnoughDist = dist; }
inline void setCloseEnoughDist3D( Bool setting ) { setFlag(IS_CLOSE_ENOUGH_DIST_3D, setting); }
inline Bool isInvalidPositionAllowed() const { return getFlag( ALLOW_INVALID_POSITION ); }
inline void setPreferredHeight( Real height ) { m_preferredHeight = height; }
#ifdef CIRCLE_FOR_LANDING
/**
if we are climbing/diving more than this, circle as needed rather
than just diving or climbing directly. (only useful for Winged things)
*/
inline void setAltitudeChangeThresholdForCircling(Real a) { m_circleThresh = a; }
#endif
/**
when off (the default), things get to adjust their z-pos as their
loco says (in particular, airborne things tend to try to fly at a preferred height).
when on, they do their best to reach the specified zpos, even if it's not at their preferred height.
this is used mainly for force missiles to swoop in on their target, and to force airplane takeoff/landing
to go smoothly.
*/
inline void setUsePreciseZPos(Bool u) { setFlag(PRECISE_Z_POS, u); }
/**
when off (the default), units slow down as they approach their target.
when on, units go full speed till the end, and may overshoot their target.
this is useful mainly in some weird, temporary situations where we know we are
going to follow this move with another one... or for carbombs.
*/
inline void setNoSlowDownAsApproachingDest(Bool u) { setFlag(NO_SLOW_DOWN_AS_APPROACHING_DEST, u); }
/**
when off (the default), units do their normal stuff.
when on, we cheat and make very precise motion, regardless of loco settings.
this is accomplished by cranking up the unit's turning rate, friction, lift (for airborne things),
and possibly other things. This is useful mainly when doing maneuvers where precision
is VITAL, such as airplane takeoff/landing.
For ground units, it also allows units to have a destination off of a pathfing grid.
*/
inline void setUltraAccurate(Bool u) { setFlag(ULTRA_ACCURATE, u); }
inline Bool isUltraAccurate() const { return getFlag(ULTRA_ACCURATE); }
inline Bool isMovingBackwards(void) const {return getFlag(MOVING_BACKWARDS);}
void startMove(void); ///< Indicates that a move is starting, primarily to reset the donut timer. jba.
protected:
void moveTowardsPositionLegs(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void moveTowardsPositionLegsWander(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void moveTowardsPositionClimb(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void moveTowardsPositionWheels(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void moveTowardsPositionTreads(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void moveTowardsPositionOther(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void moveTowardsPositionHover(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void moveTowardsPositionThrust(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void moveTowardsPositionWings(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos, Real onPathDistToGoal, Real desiredSpeed);
void maintainCurrentPositionThrust(Object* obj, PhysicsBehavior *physics);
void maintainCurrentPositionOther(Object* obj, PhysicsBehavior *physics);
void maintainCurrentPositionLegs(Object* obj, PhysicsBehavior *physics) { maintainCurrentPositionOther(obj, physics); }
void maintainCurrentPositionWheels(Object* obj, PhysicsBehavior *physics) { maintainCurrentPositionOther(obj, physics); }
void maintainCurrentPositionTreads(Object* obj, PhysicsBehavior *physics) { maintainCurrentPositionOther(obj, physics); }
void maintainCurrentPositionHover(Object* obj, PhysicsBehavior *physics);
void maintainCurrentPositionWings(Object* obj, PhysicsBehavior *physics);
PhysicsTurningType rotateTowardsPosition(Object* obj, const Coord3D& goalPos, Real *relAngle=NULL);
/*
return true if we can maintain the position without being called every frame (eg, we are
resting on the ground), false if not (eg, we are hovering or circling)
*/
Bool handleBehaviorZ(Object* obj, PhysicsBehavior *physics, const Coord3D& goalPos);
PhysicsTurningType rotateObjAroundLocoPivot(Object* obj, const Coord3D& goalPos, Real maxTurnRate, Real *relAngle = NULL);
Real getSurfaceHtAtPt(Real x, Real y);
Real calcLiftToUseAtPt(Object* obj, PhysicsBehavior *physics, Real curZ, Real surfaceAtPt, Real preferredHeight);
Bool fixInvalidPosition(Object* obj, PhysicsBehavior *physics);
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
protected:
Locomotor(const LocomotorTemplate* tmpl);
// Note, "Law of the Big Three" applies here
//Locomotor(); -- nope, we don't have a default ctor. (srj)
Locomotor(const Locomotor& that);
Locomotor& operator=(const Locomotor& that);
//~Locomotor();
private:
//
// Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE
// existing values!
//
enum LocoFlag
{
IS_BRAKING = 0,
ALLOW_INVALID_POSITION,
MAINTAIN_POS_IS_VALID,
PRECISE_Z_POS,
NO_SLOW_DOWN_AS_APPROACHING_DEST,
OVER_WATER, // To allow things to move slower/faster over water and do special effects
ULTRA_ACCURATE,
MOVING_BACKWARDS, // If we are moving backwards.
DOING_THREE_POINT_TURN, // If we are doing a 3 pt turn.
CLIMBING, // If we are in the process of climbing.
IS_CLOSE_ENOUGH_DIST_3D,
OFFSET_INCREASING
};
inline Bool getFlag(LocoFlag f) const { return (m_flags & (1 << f)) != 0; }
inline void setFlag(LocoFlag f, Bool b) { if (b) m_flags |= (1<<f); else m_flags &= ~(1<<f); }
LocomotorTemplateOverride m_template; ///< the kind of Locomotor this is
Coord3D m_maintainPos;
Real m_brakingFactor;
Real m_maxLift;
Real m_maxSpeed;
Real m_maxAccel;
Real m_maxBraking;
Real m_maxTurnRate;
Real m_closeEnoughDist;
#ifdef CIRCLE_FOR_LANDING
Real m_circleThresh;
#endif
UnsignedInt m_flags;
Real m_preferredHeight;
Real m_preferredHeightDamping;
Real m_angleOffset;
Real m_offsetIncrement;
UnsignedInt m_donutTimer; ///< Frame time to keep units from doing the donut. jba.
};
//-------------------------------------------------------------------------------------------------
/**
The "store" used to hold all the LocomotorTemplates in existence. This is usually used when creating
an Object, but can be used at any time after that. (It is explicitly
OK to swap an Object's Locomotor out at any given time.)
*/
//-------------------------------------------------------------------------------------------------
class LocomotorStore : public SubsystemInterface
{
public:
LocomotorStore();
~LocomotorStore();
void init() { };
void reset();
void update();
/**
Find the LocomotorTemplate with the given name. If no such LocomotorTemplate exists, return null.
*/
const LocomotorTemplate* findLocomotorTemplate(NameKeyType namekey) const;
LocomotorTemplate* findLocomotorTemplate(NameKeyType namekey);
inline Locomotor* newLocomotor(const LocomotorTemplate *tmpl) const
{
return newInstance(Locomotor)(tmpl); // my, that was easy
}
// locoTemplate is who we're overriding
LocomotorTemplate *newOverride(LocomotorTemplate *locoTemplate);
static void parseLocomotorTemplateDefinition(INI* ini);
protected:
private:
typedef std::map< NameKeyType, LocomotorTemplate*, std::less<NameKeyType> > LocomotorTemplateMap;
LocomotorTemplateMap m_locomotorTemplates;
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern LocomotorStore *TheLocomotorStore;
#endif // __Locomotor_H_

View file

@ -0,0 +1,114 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: LocomotorSet.h /////////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, Feb 2002
// Desc: Locomotor Descriptions
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __LocomotorSet_H_
#define __LocomotorSet_H_
// no, please do NOT include this.
//#include "GameLogic/Locomotor.h"
#include "Common/GameCommon.h"
#include "Common/STLTypedefs.h"
#include "Common/Snapshot.h"
class Locomotor;
class LocomotorTemplate;
//-------------------------------------------------------------------------------------------------
//
// Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE
// existing values!
//
enum LocomotorSurfaceType
{
LOCOMOTORSURFACE_GROUND = (1 << 0), ///< clear, unobstructed ground
LOCOMOTORSURFACE_WATER = (1 << 1), ///< water area
LOCOMOTORSURFACE_CLIFF = (1 << 2), ///< steep altitude change
LOCOMOTORSURFACE_AIR = (1 << 3), ///< airborne
LOCOMOTORSURFACE_RUBBLE = (1 << 4) ///< building rubble
};
typedef Int LocomotorSurfaceTypeMask;
const LocomotorSurfaceTypeMask NO_SURFACES = (LocomotorSurfaceTypeMask)0x0000;
const LocomotorSurfaceTypeMask ALL_SURFACES = (LocomotorSurfaceTypeMask)0xffff;
#ifdef DEFINE_SURFACECATEGORY_NAMES
static const char *TheLocomotorSurfaceTypeNames[] =
{
"GROUND",
"WATER",
"CLIFF",
"AIR",
"RUBBLE",
NULL
};
#endif
//-------------------------------------------------------------------------------------------------
typedef std::vector< Locomotor* > LocomotorVector;
//-------------------------------------------------------------------------------------------------
class LocomotorSet : public Snapshot
{
private:
LocomotorVector m_locomotors;
LocomotorSurfaceTypeMask m_validLocomotorSurfaces;
Bool m_downhillOnly;
LocomotorSet(const LocomotorSet& that);
LocomotorSet& operator=(const LocomotorSet& that);
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
public:
LocomotorSet();
~LocomotorSet();
void clear();
void addLocomotor(const LocomotorTemplate* lt);
Locomotor* findLocomotor(LocomotorSurfaceTypeMask t);
void xferSelfAndCurLocoPtr(Xfer *xfer, Locomotor** loco);
inline LocomotorSurfaceTypeMask getValidSurfaces() const { return m_validLocomotorSurfaces; }
inline Bool isDownhillOnly( void ) const { return m_downhillOnly; };
};
#endif

View file

@ -0,0 +1,95 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// LogicRandomValue.h
// Random number generation system
// Author: Michael S. Booth, January 1998
// Split out into separate Logic/Client/Audio headers by MDC Sept 2002
#pragma once
#ifndef _LOGIC_RANDOM_VALUE_H_
#define _LOGIC_RANDOM_VALUE_H_
#include "Lib/BaseType.h"
// do NOT use these functions directly, rather use the macros below
extern Int GetGameLogicRandomValue( int lo, int hi, char *file, int line );
extern Real GetGameLogicRandomValueReal( Real lo, Real hi, char *file, int line );
// use these macros to access the random value functions
#define GameLogicRandomValue( lo, hi ) GetGameLogicRandomValue( lo, hi, __FILE__, __LINE__ )
#define GameLogicRandomValueReal( lo, hi ) GetGameLogicRandomValueReal( lo, hi, __FILE__, __LINE__ )
//--------------------------------------------------------------------------------------------------------------
class CColorAlphaDialog;
class DebugWindowDialog;
/**
* A GameLogicRandomVariable represents a distribution of random values
* from which discrete values can be retrieved.
*/
class GameLogicRandomVariable
{
public:
// NOTE: This class cannot have a constructor or destructor due to its use within unions
/**
* CONSTANT represents a single, constant, value.
* UNIFORM represents a uniform distribution of random values.
* GAUSSIAN represents a normally distributed set of random values.
* TRIANGULAR represents a distribution of random values in the shape
* of a triangle, with the peak probability midway between low and high.
* LOW_BIAS represents a distribution of random values with
* maximum probability at low, and zero probability at high.
* HIGH_BIAS represents a distribution of random values with
* zero probability at low, and maximum probability at high.
*/
enum DistributionType
{
CONSTANT, UNIFORM, GAUSSIAN, TRIANGULAR, LOW_BIAS, HIGH_BIAS
};
static const char *DistributionTypeNames[];
/// define the range of random values, and the distribution of values
void setRange( Real low, Real high, DistributionType type = UNIFORM );
Real getValue( void ) const; ///< return a value from the random distribution
inline Real getMinimumValue( void ) const { return m_low; }
inline Real getMaximumValue( void ) const { return m_high; }
inline DistributionType getDistributionType( void ) const { return m_type; }
protected:
DistributionType m_type; ///< the kind of random distribution
Real m_low, m_high; ///< the range of random values
// These two friends are for particle editing.
friend CColorAlphaDialog;
friend DebugWindowDialog;
};
//--------------------------------------------------------------------------------------------------------------
#endif // _LOGIC_RANDOM_VALUE_H_

View file

@ -0,0 +1,806 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// AIUpdate.h //
// AI interface
// Author: Michael S. Booth, 2001-2002
#pragma once
#ifndef _AI_UPDATE_H_
#define _AI_UPDATE_H_
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/AI.h"
#include "GameLogic/AIStateMachine.h"
#include "GameLogic/GameLogic.h"
#include "GameLogic/LocomotorSet.h"
class AIGroup;
class AIStateMachine;
class AttackPriorityInfo;
class DamageInfo;
class DozerAIInterface;
class Object;
class Path;
class PathfindServicesInterface;
class PathNode;
class PhysicsBehavior;
#ifdef ALLOW_SURRENDER
class POWTruckAIUpdateInterface;
#endif
class SupplyTruckAIInterface;
class TurretAI;
class TurretAIData;
class Waypoint;
class WorkerAIInterface;
class HackInternetAIInterface;
class AssaultTransportAIInterface;
class JetAIUpdate;
enum AIStateType;
enum ObjectID;
//-------------------------------------------------------------------------------------------------
const Real FAST_AS_POSSIBLE = 999999.0f;
//-------------------------------------------------------------------------------------------------
//
// Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE
// existing values!
//
enum LocomotorSetType
{
LOCOMOTORSET_INVALID = -1,
LOCOMOTORSET_NORMAL = 0,
LOCOMOTORSET_NORMAL_UPGRADED,
LOCOMOTORSET_FREEFALL,
LOCOMOTORSET_WANDER,
LOCOMOTORSET_PANIC,
LOCOMOTORSET_TAXIING, // set used for normally-airborne items while taxiing on ground
LOCOMOTORSET_SUPERSONIC, // set used for high-speed attacks
LOCOMOTORSET_SLUGGISH, // set used for abnormally slow (but not damaged) speeds
LOCOMOTORSET_COUNT ///< keep last, please
};
//-------------------------------------------------------------------------------------------------
enum GuardTargetType
{
GUARDTARGET_LOCATION, // Guard a coord3d
GUARDTARGET_OBJECT, // Guard an object
GUARDTARGET_AREA, // Guard a Polygon trigger
GUARDTARGET_NONE // Currently not guarding
};
#ifdef DEFINE_LOCOMOTORSET_NAMES
static const char *TheLocomotorSetNames[] =
{
"SET_NORMAL",
"SET_NORMAL_UPGRADED",
"SET_FREEFALL",
"SET_WANDER",
"SET_PANIC",
"SET_TAXIING",
"SET_SUPERSONIC",
"SET_SLUGGISH",
NULL
};
#endif
enum AutoAcquireStates
{
AAS_Idle = 0x01,
AAS_Idle_Stealthed = 0x02,
AAS_Idle_No = 0x04,
AAS_Idle_Not_While_Attacking = 0x08,
AAS_Idle_Attack_Buildings = 0x10,
};
#ifdef DEFINE_AUTOACQUIRE_NAMES
static const char *TheAutoAcquireEnemiesNames[] =
{
"YES",
"STEALTHED",
"NO",
"NOTWHILEATTACKING",
"ATTACK_BUILDINGS",
NULL
};
#endif
//-------------------------------------------------------------------------------------------------
enum MoodMatrixParameters
{
// Controller_Player and Controller_AI are mutually exclusive
MM_Controller_Player = 0x00000001,
MM_Controller_AI = 0x00000002,
MM_Controller_Bitmask = (MM_Controller_Player | MM_Controller_AI),
// UnitTypes are mutually exclusive, ie: you cannot be turreted and air at the same time (we do
// not make such a distinction, so air takes precedence over turretedness)
MM_UnitType_NonTurreted = 0x00000010,
MM_UnitType_Turreted = 0x00000020,
MM_UnitType_Air = 0x00000040,
MM_UnitType_Bitmask = (MM_UnitType_NonTurreted | MM_UnitType_Turreted | MM_UnitType_Air),
// A unit can be in only one mood at a time.
MM_Mood_Sleep = 0x00000100,
MM_Mood_Passive = 0x00000200,
MM_Mood_Normal = 0x00000400,
MM_Mood_Alert = 0x00000800,
MM_Mood_Aggressive = 0x00001000,
MM_Mood_Bitmask = (MM_Mood_Sleep | MM_Mood_Passive | MM_Mood_Normal | MM_Mood_Alert | MM_Mood_Aggressive)
};
//-------------------------------------------------------------------------------------------------
enum MoodMatrixAction
{
MM_Action_Idle,
MM_Action_Move,
MM_Action_Attack,
MM_Action_AttackMove
};
//-------------------------------------------------------------------------------------------------
enum MoodActionAdjustment
{
MAA_Action_Ok = 0x00000001,
MAA_Action_To_Idle = 0x00000002,
MAA_Action_To_AttackMove = 0x00000004,
MAA_Action_To_Bitmask = (MAA_Action_Ok | MAA_Action_To_Idle | MAA_Action_To_AttackMove),
MAA_Affect_Range_IgnoreAll = 0x00000010,
MAA_Affect_Range_WaitForAttack = 0x00000020,
// Normal doesn't affect ranges.
MAA_Affect_Range_Alert = 0x00000040,
MAA_Affect_Range_Aggressive = 0x00000080,
MAA_Affect_Range_Bitmask = (MAA_Affect_Range_IgnoreAll | MAA_Affect_Range_WaitForAttack | MAA_Affect_Range_Alert | MAA_Affect_Range_Aggressive)
};
//-------------------------------------------------------------------------------------------------
typedef std::vector< const LocomotorTemplate* > LocomotorTemplateVector;
typedef std::map< LocomotorSetType, LocomotorTemplateVector, std::less<LocomotorSetType> > LocomotorTemplateMap;
//-------------------------------------------------------------------------------------------------
class AIUpdateModuleData : public UpdateModuleData
{
public:
LocomotorTemplateMap m_locomotorTemplates; ///< locomotors for object
const TurretAIData* m_turretData[MAX_TURRETS];
UnsignedInt m_moodAttackCheckRate; ///< how frequently we should recheck for enemies due to moods, when idle
Bool m_forbidPlayerCommands; ///< Should isAllowedToRespondToAiCommands() filter out commands from the player, thus making it ai-controllable only?
Bool m_turretsLinked; ///< Turrets are linked together and attack together.
UnsignedInt m_autoAcquireEnemiesWhenIdle;
#ifdef ALLOW_SURRENDER
UnsignedInt m_surrenderDuration; ///< when we surrender, how long we stay surrendered.
#endif
AIUpdateModuleData();
virtual ~AIUpdateModuleData();
virtual Bool isAiModuleData() const { return true; }
const LocomotorTemplateVector* findLocomotorTemplateVector(LocomotorSetType t) const;
static void buildFieldParse(MultiIniFieldParse& p);
static void parseLocomotorSet( INI* ini, void *instance, void *store, const void* /*userData*/ );
private:
static void parseTurret( INI* ini, void *instance, void *store, const void* /*userData*/ );
};
//-------------------------------------------------------------------------------------------------
enum AIFreeToExitType // Note - written out in save/load xfer, don't change these numbers. jba.
{
FREE_TO_EXIT=0,
NOT_FREE_TO_EXIT=1,
WAIT_TO_EXIT=2
};
//-------------------------------------------------------------------------------------------------
/**
* The AIUpdateInterface module contains the interface to the AI system,
* and performs the actual AI behaviors.
*/
class AIUpdateInterface : public UpdateModule, public AICommandInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AIUpdateInterface, "AIUpdateInterface" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AIUpdateInterface, AIUpdateModuleData )
protected:
// yes, protected, NOT public.
virtual void privateMoveToPosition( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s) tightening the formation.
virtual void privateMoveToObject( Object *obj, CommandSourceType cmdSource ); ///< move to given object
virtual void privateMoveToAndEvacuate( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s)
virtual void privateMoveToAndEvacuateAndExit( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position & unload transport.
virtual void privateIdle(CommandSourceType cmdSource); ///< Enter idle state.
virtual void privateTightenToPosition( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s) tightening the formation.
virtual void privateFollowWaypointPath( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point
virtual void privateFollowWaypointPathAsTeam( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point
virtual void privateFollowWaypointPathExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point
virtual void privateFollowWaypointPathAsTeamExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point
virtual void privateFollowPath( const std::vector<Coord3D>* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points
virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource );
virtual void privateAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object
virtual void privateForceAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object
virtual void privateGuardRetaliate( Object *victim, const Coord3D *pos, Int maxShotsToFire, CommandSourceType cmdSource ); ///< retaliate and attack attacker -- but with guard restrictions
virtual void privateAttackTeam( const Team *team, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack the given team
virtual void privateAttackPosition( const Coord3D *pos, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given spot
virtual void privateAttackMoveToPosition( const Coord3D *pos, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack move to the given location
virtual void privateAttackFollowWaypointPath( const Waypoint *way, Int maxShotsToFire, Bool asTeam, CommandSourceType cmdSource ); ///< attack move along the following waypoint path, potentially as a team
virtual void privateHunt( CommandSourceType cmdSource ); ///< begin "seek and destroy"
virtual void privateRepair( Object *obj, CommandSourceType cmdSource ); ///< repair the given object
#ifdef ALLOW_SURRENDER
virtual void privatePickUpPrisoner( Object *prisoner, CommandSourceType cmdSource ); ///< pick up prisoner
virtual void privateReturnPrisoners( Object *prison, CommandSourceType cmdSource ); ///< return picked up prisoners to the 'prison'
#endif
virtual void privateResumeConstruction( Object *obj, CommandSourceType cmdSource ); ///< resume construction of object
virtual void privateGetHealed( Object *healDepot, CommandSourceType cmdSource ); ///< get healed at heal depot
virtual void privateGetRepaired( Object *repairDepot, CommandSourceType cmdSource );///< get repaired at repair depot
virtual void privateEnter( Object *obj, CommandSourceType cmdSource ); ///< enter the given object
virtual void privateDock( Object *obj, CommandSourceType cmdSource ); ///< get near given object and wait for enter clearance
virtual void privateExit( Object *objectToExit, CommandSourceType cmdSource ); ///< get out of this Object
virtual void privateExitInstantly( Object *objectToExit, CommandSourceType cmdSource ); ///< get out of this Object this frame
virtual void privateEvacuate( Int exposeStealthUnits, CommandSourceType cmdSource ); ///< empty its contents
virtual void privateEvacuateInstantly( Int exposeStealthUnits, CommandSourceType cmdSource ); ///< empty its contents this frame
virtual void privateExecuteRailedTransport( CommandSourceType cmdSource ); ///< execute next leg in railed transport sequence
virtual void privateGoProne( const DamageInfo *damageInfo, CommandSourceType cmdSource ); ///< life altering state change, if this AI can do it
virtual void privateGuardTunnelNetwork( GuardMode guardMode, CommandSourceType cmdSource ); ///< guard the given spot
virtual void privateGuardPosition( const Coord3D *pos, GuardMode guardMode, CommandSourceType cmdSource ); ///< guard the given spot
virtual void privateGuardObject( Object *objectToGuard, GuardMode guardMode, CommandSourceType cmdSource ); ///< guard the given object
virtual void privateGuardArea( const PolygonTrigger *areaToGuard, GuardMode guardMode, CommandSourceType cmdSource ); ///< guard the given area
virtual void privateAttackArea( const PolygonTrigger *areaToGuard, CommandSourceType cmdSource ); ///< guard the given area
virtual void privateHackInternet( CommandSourceType cmdSource ); ///< Hack money from the heavens (free money)
virtual void privateFaceObject( Object *target, CommandSourceType cmdSource );
virtual void privateFacePosition( const Coord3D *pos, CommandSourceType cmdSource );
virtual void privateRappelInto( Object *target, const Coord3D& pos, CommandSourceType cmdSource );
virtual void privateCombatDrop( Object *target, const Coord3D& pos, CommandSourceType cmdSource );
virtual void privateCommandButton( const CommandButton *commandButton, CommandSourceType cmdSource );
virtual void privateCommandButtonPosition( const CommandButton *commandButton, const Coord3D *pos, CommandSourceType cmdSource );
virtual void privateCommandButtonObject( const CommandButton *commandButton, Object *obj, CommandSourceType cmdSource );
virtual void privateWander( const Waypoint *way, CommandSourceType cmdSource ); ///< Wander around the waypoint path.
virtual void privateWanderInPlace( CommandSourceType cmdSource ); ///< Wander around the current position.
virtual void privatePanic( const Waypoint *way, CommandSourceType cmdSource ); ///< Run screaming down the waypoint path.
virtual void privateBusy( CommandSourceType cmdSource ); ///< Transition to the busy state
virtual void privateMoveAwayFromUnit( Object *unit, CommandSourceType cmdSource ); ///< Move out of the way of a unit.
public:
AIUpdateInterface( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual AIUpdateInterface* getAIUpdateInterface() { return this; }
// Disabled conditions to process (AI will still process held status)
virtual DisabledMaskType getDisabledTypesToProcess() const { return MAKE_DISABLED_MASK( DISABLED_HELD ); }
// Some very specific, complex behaviors are used by more than one AIUpdate. Here are their interfaces.
virtual DozerAIInterface* getDozerAIInterface() {return NULL;}
virtual SupplyTruckAIInterface* getSupplyTruckAIInterface() {return NULL;}
virtual const DozerAIInterface* getDozerAIInterface() const {return NULL;}
virtual const SupplyTruckAIInterface* getSupplyTruckAIInterface() const {return NULL;}
#ifdef ALLOW_SURRENDER
virtual POWTruckAIUpdateInterface *getPOWTruckAIUpdateInterface( void ) { return NULL; }
#endif
virtual WorkerAIInterface* getWorkerAIInterface( void ) { return NULL; }
virtual const WorkerAIInterface* getWorkerAIInterface( void ) const { return NULL; }
virtual HackInternetAIInterface* getHackInternetAIInterface() { return NULL; }
virtual const HackInternetAIInterface* getHackInternetAIInterface() const { return NULL; }
virtual AssaultTransportAIInterface* getAssaultTransportAIInterface() { return NULL; }
virtual const AssaultTransportAIInterface* getAssaultTransportAIInterface() const { return NULL; }
virtual JetAIUpdate* getJetAIUpdate() { return NULL; }
virtual const JetAIUpdate* getJetAIUpdate() const { return NULL; }
#ifdef ALLOW_SURRENDER
void setSurrendered( const Object *objWeSurrenderedTo, Bool surrendered );
inline Bool isSurrendered( void ) const { return m_surrenderedFramesLeft > 0; }
inline Int getSurrenderedPlayerIndex() const { return m_surrenderedPlayerIndex; }
#endif
virtual void joinTeam( void ); ///< This unit just got added to a team & needs to catch up.
Bool areTurretsLinked() const { return getAIUpdateModuleData()->m_turretsLinked; }
// this is present solely for some transports to override, so that they can land before
// allowing people to exit...
virtual AIFreeToExitType getAiFreeToExit(const Object* exiter) const { return FREE_TO_EXIT; }
// this is present solely to allow some special-case things to override, like landed choppers.
virtual Bool isAllowedToAdjustDestination() const { return true; }
virtual Bool isAllowedToMoveAwayFromUnit() const { return true; }
// this is used for Chinooks, so the pathfinder doesn't make 'em avoid 'em... for combat drops!
virtual ObjectID getBuildingToNotPathAround() const { return INVALID_ID; }
// AI Interface implementation -----------------------------------------------------------------------
virtual Bool isIdle() const;
virtual Bool isAttacking() const;
virtual Bool isClearingMines() const;
virtual Bool isTaxiingToParking() const { return FALSE; } //only applies to jets interacting with runways.
//Definition of busy -- when explicitly in the busy state. Moving or attacking is not considered busy!
virtual Bool isBusy() const;
virtual void onObjectCreated();
virtual void doQuickExit( const std::vector<Coord3D>* path ); ///< get out of this Object
virtual void aiDoCommand(const AICommandParms* parms);
virtual const Coord3D *getGuardLocation( void ) const { return &m_locationToGuard; }
virtual const ObjectID getGuardObject( void ) const { return m_objectToGuard; }
virtual const PolygonTrigger *getAreaToGuard( void ) const { return m_areaToGuard; }
virtual GuardTargetType getGuardTargetType() const { return m_guardTargetType[1]; }
virtual void clearGuardTargetType() { m_guardTargetType[1] = m_guardTargetType[0]; m_guardTargetType[0] = GUARDTARGET_NONE; }
virtual GuardMode getGuardMode() const { return m_guardMode; }
virtual Object* construct( const ThingTemplate *what,
const Coord3D *pos, Real angle,
Player *owningPlayer,
Bool isRebuild ) { return NULL; }///< construct a building
void ignoreObstacle( const Object *obj ); ///< tell the pathfinder to ignore the given object as an obstacle
void ignoreObstacleID( ObjectID id ); ///< tell the pathfinder to ignore the given object as an obstacle
AIStateType getAIStateType() const; ///< What general state is the AIState Machine in?
AsciiString getCurrentStateName(void) const { return m_stateMachine->getCurrentStateName(); }
virtual Object* getEnterTarget(); ///< if we are trying to enter something (see enter() above), what is the thing in question? (or null)
/**
This exists solely to be overridden by children... the idea is that when a unit is targeted by someone else, it
asks for an offset to add to its targeting position... if this returns true, the offset should be added to the
true target pos. This is primarily for the Aurora Bomber, which uses this technique to make itself "unhittable"
when in Supersonic Attack Mode -- things still target it, they just aim "behind" it!
*/
virtual Bool getSneakyTargetingOffset(Coord3D* offset) const { return false; }
/**
Exists solely to be overridden by JetAIUpdate...
*/
virtual void addTargeter(ObjectID id, Bool add) { return; }
virtual Bool isTemporarilyPreventingAimSuccess() const { return false; }
void setPriorWaypointID( UnsignedInt id ) { m_priorWaypointID = id; };
void setCurrentWaypointID( UnsignedInt id ) { m_currentWaypointID = id; };
// Group ----------------------------------------------------------------------------------------------
// these three methods allow a group leader's path to be communicated to the other group members
AIGroup *getGroup(void);
// it's VERY RARE you want to call this function; you should normally use Object::isEffectivelyDead()
// instead. the exception would be for things that need to know whether to call markIsDead or not.
Bool isAiInDeadState( void ) const { return m_isAiDead; } ///< return true if we are dead
void markAsDead( void );
Bool isRecruitable(void) const {return m_isRecruitable;}
void setIsRecruitable(Bool isRecruitable) {m_isRecruitable = isRecruitable;}
Real getDesiredSpeed() const { return m_desiredSpeed; }
void setDesiredSpeed( Real speed ) { m_desiredSpeed = speed; } ///< how fast we want to go
// these are virtual because subclasses might need to override them. (srj)
virtual void setLocomotorGoalPositionOnPath();
virtual void setLocomotorGoalPositionExplicit(const Coord3D& newPos);
virtual void setLocomotorGoalOrientation(Real angle);
virtual void setLocomotorGoalNone();
virtual Bool isDoingGroundMovement(void) const; ///< True if moving along ground.
Bool isValidLocomotorPosition(const Coord3D* pos) const;
Bool isAircraftThatAdjustsDestination(void) const; ///< True if is aircraft that doesn't stack destinations (missles for example do stack destinations.)
Real getCurLocomotorSpeed() const;
Real getLocomotorDistanceToGoal();
const Locomotor *getCurLocomotor() const {return m_curLocomotor;}
Locomotor *getCurLocomotor() { return m_curLocomotor; }
LocomotorSetType getCurLocomotorSetType() const { return m_curLocomotorSet; }
Bool hasLocomotorForSurface(LocomotorSurfaceType surfaceType);
// turret stuff.
WhichTurretType getWhichTurretForWeaponSlot(WeaponSlotType wslot, Real* turretAngle, Real* turretPitch = NULL) const;
WhichTurretType getWhichTurretForCurWeapon() const;
/**
return true iff the weapon is on a turret, that turret is trying to aim at the victim,
BUT is not yet pointing in the right dir.
*/
Bool isWeaponSlotOnTurretAndAimingAtTarget(WeaponSlotType wslot, const Object* victim) const;
Bool getTurretRotAndPitch(WhichTurretType tur, Real* turretAngle, Real* turretPitch) const;
Real getTurretTurnRate(WhichTurretType tur) const;
void setTurretTargetObject(WhichTurretType tur, Object* o, Bool isForceAttacking = FALSE);
Object *getTurretTargetObject( WhichTurretType tur, Bool clearDeadTargets = TRUE );
void setTurretTargetPosition(WhichTurretType tur, const Coord3D* pos);
void setTurretEnabled(WhichTurretType tur, Bool enabled);
void recenterTurret(WhichTurretType tur);
Bool isTurretEnabled( WhichTurretType tur ) const;
Bool isTurretInNaturalPosition(WhichTurretType tur) const;
// "Planning Mode" -----------------------------------------------------------------------------------
Bool queueWaypoint( const Coord3D *pos ); ///< add waypoint to end of move list. return true if success, false if queue was full and those the waypoint not added
void clearWaypointQueue( void ); ///< reset the waypoint queue to empty
void executeWaypointQueue( void ); ///< start moving along queued waypoints
// Pathfinding ---------------------------------------------------------------------------------------
private:
Bool computePath( PathfindServicesInterface *pathfinder, Coord3D *destination ); ///< computes path to destination, returns false if no path
Bool computeAttackPath(PathfindServicesInterface *pathfinder, const Object *victim, const Coord3D* victimPos ); ///< computes path to attack the current target, returns false if no path
#ifdef ALLOW_SURRENDER
void doSurrenderUpdateStuff();
#endif
public:
void doPathfind( PathfindServicesInterface *pathfinder );
void requestPath( Coord3D *destination, Bool isGoalDestination ); ///< Queues a request to pathfind to destination.
void requestAttackPath( ObjectID victimID, const Coord3D* victimPos ); ///< computes path to attack the current target, returns false if no path
void requestApproachPath( Coord3D *destination ); ///< computes path to attack the current target, returns false if no path
void requestSafePath( ObjectID repulsor1 ); ///< computes path to attack the current target, returns false if no path
Bool isWaitingForPath(void) const {return m_waitingForPath;}
Bool isAttackPath(void) const {return m_isAttackPath;} ///< True if we have a path to an attack location.
void cancelPath(void); ///< Called if we no longer need the path.
Path* getPath( void ) { return m_path; } ///< return the agent's current path
const Path* getPath( void ) const { return m_path; } ///< return the agent's current path
void destroyPath( void ); ///< destroy the current path, setting it to NULL
UnsignedInt getPathAge( void ) const { return TheGameLogic->getFrame() - m_pathTimestamp; } ///< return the "age" of the path
Bool isPathAvailable( const Coord3D *destination ) const; ///< does a path exist between us and the destination
Bool isQuickPathAvailable( const Coord3D *destination ) const; ///< does a path (using quick pathfind) exist between us and the destination
Int getNumFramesBlocked(void) const {return m_blockedFrames;}
Bool isBlockedAndStuck(void) const {return m_isBlockedAndStuck;}
Bool canComputeQuickPath(void); ///< Returns true if we can quickly comput a path. Usually missiles & the like that just move straight to the destination.
Bool computeQuickPath(const Coord3D *destination); ///< Computes a quick path to the destination.
Bool isMoving() const;
Bool isMovingAwayFrom(Object *obj) const;
// the following routines should only be called by the AIInternalMoveToState.
// They are used to determine when we are really through moving. Due to the nature of the beast,
// we often exit one move state & immediately enter another. This should not cause a "stop start".
// jba.
void friend_startingMove(void);
void friend_endingMove(void);
void friend_setPath(Path *newPath);
Path* friend_getPath() { return m_path; }
void friend_setGoalObject(Object *obj);
virtual Bool processCollision(PhysicsBehavior *physics, Object *other); ///< Returns true if the physics collide should apply the force. Normally not. jba.
ObjectID getIgnoredObstacleID( void ) const;
// "Waypoint Mode" -----------------------------------------------------------------------------------
const Waypoint *getCompletedWaypoint(void) const {return m_completedWaypoint;}
void setCompletedWaypoint(const Waypoint *pWay) {m_completedWaypoint = pWay;}
const LocomotorSet& getLocomotorSet(void) const {return m_locomotorSet;}
void setPathExtraDistance(Real dist) {m_pathExtraDistance = dist;}
inline Real getPathExtraDistance() const { return m_pathExtraDistance; }
virtual Bool chooseLocomotorSet(LocomotorSetType wst);
virtual CommandSourceType getLastCommandSource() const { return m_lastCommandSource; }
const AttackPriorityInfo *getAttackInfo(void) {return m_attackInfo;}
void setAttackInfo(const AttackPriorityInfo *info) {m_attackInfo = info;}
void setCurPathfindCell(const ICoord2D &cell) {m_pathfindCurCell = cell;}
void setPathfindGoalCell(const ICoord2D &cell) {m_pathfindGoalCell = cell;}
void setPathFromWaypoint(const Waypoint *way, const Coord2D *offset);
const ICoord2D *getCurPathfindCell(void) const {return &m_pathfindCurCell;}
const ICoord2D *getPathfindGoalCell(void) const {return &m_pathfindGoalCell;}
/// Return true if our path has higher priority.
Bool hasHigherPathPriority(AIUpdateInterface *otherAI) const;
void setFinalPosition(const Coord3D *pos) { m_finalPosition = *pos; m_doFinalPosition = false;}
virtual UpdateSleepTime update( void ); ///< update this object's AI
/// if we are attacking "fromID", stop that and attack "toID" instead
void transferAttack(ObjectID fromID, ObjectID toID);
void setCurrentVictim( const Object *nemesis ); ///< Current victim.
Object *getCurrentVictim( void ) const;
virtual void notifyVictimIsDead() { }
// if we are attacking a position (and NOT an object), return it. otherwise return null.
const Coord3D *getCurrentVictimPos( void ) const;
void setLocomotorUpgrade(Bool set);
// This function is used to notify the unit that it may have a target of opportunity to attack.
void wakeUpAndAttemptToTarget( void );
void resetNextMoodCheckTime( void );
//Specifically set a frame to check next mood time -- added for the purpose of ordering a stealth combat unit that can't
//autoacquire while stealthed, but isn't stealthed and can stealth and is not detected, and the player specifically orders
//that unit to stop. In this case, instead of the unit autoacquiring another unit, and preventing him from stealthing,
//we will instead delay the autoacquire until later to give him enough time to stealth properly.
void setNextMoodCheckTime( UnsignedInt frame );
///< States should call this with calledByAI set true to prevent them from checking every frame
///< States that are doing idle checks should call with calledDuringIdle set true so that they check their
Object *getNextMoodTarget( Bool calledByAI, Bool calledDuringIdle );
UnsignedInt getNextMoodCheckTime() const { return m_nextMoodCheckTime; }
// This function will return a combination of MoodMatrixParameter flags.
UnsignedInt getMoodMatrixValue( void ) const;
UnsignedInt getMoodMatrixActionAdjustment( MoodMatrixAction action ) const;
void setAttitude( AttitudeType tude ); ///< set the behavior modifier for this agent
// Common AI "status" effects -------------------------------------------------------------------
void evaluateMoraleBonus( void );
#ifdef ALLOW_DEMORALIZE
// demoralization ... what a nifty word to write.
Bool isDemoralized( void ) const { return m_demoralizedFramesLeft > 0; }
void setDemoralized( UnsignedInt durationInFrames );
#endif
Bool canPathThroughUnits( void ) const { return m_canPathThroughUnits; }
void setCanPathThroughUnits( Bool canPath ) { m_canPathThroughUnits = canPath; if (canPath) m_isBlockedAndStuck=false;}
// Notify the ai that it has caused a crate to be created (usually by killing something.)
void notifyCrate(ObjectID id) { m_crateCreated = id; }
ObjectID getCrateID(void) const { return m_crateCreated; }
Object* checkForCrateToPickup();
void setIgnoreCollisionTime(Int frames) { m_ignoreCollisionsUntil = TheGameLogic->getFrame() + frames; }
void setQueueForPathTime(Int frames);
// For the attack move, that switches from move to attack, and the attack is CMD_FROM_AI,
// while the move is the original command source. John A.
void friend_setLastCommandSource( CommandSourceType source ) {m_lastCommandSource = source;}
Bool canAutoAcquire() const { return getAIUpdateModuleData()->m_autoAcquireEnemiesWhenIdle; }
Bool canAutoAcquireWhileStealthed() const ;
protected:
/*
AIUpdates run in the initial phase.
It's actually quite important that AI (the thing that drives Locomotors) and Physics
run in the same order, relative to each other, for a given object; otherwise,
interesting oscillations can occur in some situations, with friction being applied
either before or after the locomotive force, making for huge stuttery messes. (srj)
*/
virtual SleepyUpdatePhase getUpdatePhase() const { return PHASE_INITIAL; }
void setGoalPositionClipped(const Coord3D* in, CommandSourceType cmdSource);
virtual Bool isAllowedToRespondToAiCommands(const AICommandParms* parms) const;
// getAttitude is protected because other places should call getMoodMatrixValue to get all the facts they need to consider.
AttitudeType getAttitude( void ) const; ///< get the current behavior modifier state.
Bool blockedBy(Object *other); ///< Returns true if we are blocked by "other"
Bool needToRotate(void); ///< Returns true if we are not pointing in the right direction for movement.
Real calculateMaxBlockedSpeed(Object *other) const;
virtual UpdateSleepTime doLocomotor(); // virtual so subclasses can override
void chooseGoodLocomotorFromCurrentSet();
void setLastCommandSource( CommandSourceType source );
// subclasses may want to override this, to use a subclass of AIStateMachine.
virtual AIStateMachine* makeStateMachine();
virtual Bool getTreatAsAircraftForLocoDistToGoal() const;
// yes, protected, NOT public... try to avoid exposing the state machine directly, please
inline AIStateMachine* getStateMachine() { return m_stateMachine; }
inline const AIStateMachine* getStateMachine() const { return m_stateMachine; }
void wakeUpNow();
public:
inline StateID getCurrentStateID() const { return getStateMachine()->getCurrentStateID(); } ///< return the id of the current state of the machine
/// @ todo -- srj sez: JBA NUKE THIS CODE, IT IS EVIL
inline void friend_addToWaypointGoalPath( const Coord3D *pathPoint ) { getStateMachine()->addToGoalPath(pathPoint); }
// this is intended for use ONLY by W3dWaypointBuffer and AIFollowPathState.
inline const Coord3D* friend_getGoalPathPosition( Int index ) const { return getStateMachine()->getGoalPathPosition( index ); }
// this is intended for use ONLY by W3dWaypointBuffer.
Int friend_getWaypointGoalPathSize() const;
// this is intended for use ONLY by W3dWaypointBuffer.
inline Int friend_getCurrentGoalPathIndex() const { return m_nextGoalPathIndex; }
// this is intended for use ONLY by AIFollowPathState.
inline void friend_setCurrentGoalPathIndex( Int index ) { m_nextGoalPathIndex = index; }
#if defined(_DEBUG) || defined(_INTERNAL)
inline const Coord3D *friend_getRequestedDestination() const { return &m_requestedDestination; }
inline const Coord3D *friend_getRequestedDestination2() const { return &m_requestedDestination2; }
#endif
inline Object* getGoalObject() { return getStateMachine()->getGoalObject(); } ///< return the id of the current state of the machine
inline const Coord3D* getGoalPosition() const { return getStateMachine()->getGoalPosition(); } ///< return the id of the current state of the machine
inline WhichTurretType friend_getTurretSync() const { return m_turretSyncFlag; }
inline void friend_setTurretSync(WhichTurretType t) { m_turretSyncFlag = t; }
inline UnsignedInt getPriorWaypointID ( void ) { return m_priorWaypointID; };
inline UnsignedInt getCurrentWaypointID ( void ) { return m_currentWaypointID; };
inline void clearMoveOutOfWay(void) {m_moveOutOfWay1 = INVALID_ID; m_moveOutOfWay2 = INVALID_ID;}
inline void setTmpValue(Int val) {m_tmpInt = val;}
inline Int getTmpValue(void) {return m_tmpInt;}
inline Bool getRetryPath(void) {return m_retryPath;}
inline void setAllowedToChase( Bool allow ) { m_allowedToChase = allow; }
inline Bool isAllowedToChase() const { return m_allowedToChase; }
// only for AIStateMachine.
virtual void friend_notifyStateMachineChanged();
private:
// this should only be called by load/save, or by chooseLocomotorSet.
// it does no sanity checking; it just jams it in.
Bool chooseLocomotorSetExplicit(LocomotorSetType wst);
private:
UnsignedInt m_priorWaypointID; ///< ID of the path we follwed to before the most recent one
UnsignedInt m_currentWaypointID; ///< ID of the most recent one...
AIStateMachine* m_stateMachine; ///< the state machine
UnsignedInt m_nextEnemyScanTime; ///< how long until the next enemy scan
ObjectID m_currentVictimID; ///< if not INVALID_ID, this agent's current victim.
Real m_desiredSpeed; ///< the desired speed of the tank
CommandSourceType m_lastCommandSource; /**< Keep track of the source of the last command we got.
This is set immediately before the SetState that goes
to the state machine, so onEnter in there can know where
the command came from.
*/
GuardMode m_guardMode;
GuardTargetType m_guardTargetType[2];
Coord3D m_locationToGuard;
ObjectID m_objectToGuard;
const PolygonTrigger* m_areaToGuard;
// Attack Info --------------------------------------------------------------------------------------------
const AttackPriorityInfo* m_attackInfo;
// "Planning Mode" -----------------------------------------------------------------------------------------
enum { MAX_WAYPOINTS = 16 };
Coord3D m_waypointQueue[ MAX_WAYPOINTS ]; ///< the waypoint queue
Int m_waypointCount; ///< number of waypoints in the queue
Int m_waypointIndex; ///< current waypoint we are moving to
const Waypoint* m_completedWaypoint; ///< Set to the last waypoint in a path when the FollowWaypointPath is complete.
// Pathfinding ---------------------------------------------------------------------------------------------
Path* m_path; ///< current path to follow (for moving)
ObjectID m_requestedVictimID;
Coord3D m_requestedDestination;
Coord3D m_requestedDestination2;
UnsignedInt m_pathTimestamp; ///< time of path construction
ObjectID m_ignoreObstacleID; ///< ignore this obstacle when pathfinding
Real m_pathExtraDistance; ///< If we are following a waypoint path, there will be extra distance beyond the current path.
ICoord2D m_pathfindGoalCell; ///< Cell we are moving towards.
ICoord2D m_pathfindCurCell; ///< Cell we are currently occupying.
Int m_blockedFrames; ///< Number of frames we've been blocked.
Real m_curMaxBlockedSpeed; ///< Max speed we can have and not run into blocking things.
Real m_bumpSpeedLimit; ///< Max speed after bumping a unit.
UnsignedInt m_ignoreCollisionsUntil; ///< Timer to cheat if we get stuck.
/**
If nonzero and >= now, frame when we should queueForPath.
NEVER EVER EVER set this directly. you must call setQueueForPathTime() in ALL CASES.
NEVER EVER EVER set this directly. you must call setQueueForPathTime() in ALL CASES.
NEVER EVER EVER set this directly. you must call setQueueForPathTime() in ALL CASES.
NEVER EVER EVER set this directly. you must call setQueueForPathTime() in ALL CASES.
*/
UnsignedInt m_queueForPathFrame;
Coord3D m_finalPosition; ///< Final position for the moveto states.
ObjectID m_repulsor1; ///< First object we are running away from.
ObjectID m_repulsor2; ///< Second object we are running away from.
Int m_nextGoalPathIndex; ///< The simple goal path index we are moving to next.
ObjectID m_moveOutOfWay1;
ObjectID m_moveOutOfWay2;
// Locomotors -------------------------------------------------------------------------------------------------
enum LocoGoalType // Note - written out in save/load xfer, don't change these numbers. jba.
{
NONE = 0,
POSITION_ON_PATH = 1,
POSITION_EXPLICIT = 2,
ANGLE = 3
};
LocomotorSet m_locomotorSet;
Locomotor* m_curLocomotor;
LocomotorSetType m_curLocomotorSet;
LocoGoalType m_locomotorGoalType;
Coord3D m_locomotorGoalData;
// Turrets -------------------------------------------------------------------------------------------------
TurretAI* m_turretAI[MAX_TURRETS]; // ai for our turret (or null if no turret)
WhichTurretType m_turretSyncFlag; ///< for private use by multiturreted units where the turrets must sync with each other
// AI -------------------------------------------------------------------------------------------
AttitudeType m_attitude;
UnsignedInt m_nextMoodCheckTime;
// Common AI "status" effects -------------------------------------------------------------------
#ifdef ALLOW_DEMORALIZE
UnsignedInt m_demoralizedFramesLeft;
#endif
#ifdef ALLOW_SURRENDER
UnsignedInt m_surrenderedFramesLeft; ///< Non-zero when in a surrendered state
Int m_surrenderedPlayerIndex; ///< if surrendered, the playerindex to whom we are surrendered, or -1 if available for everyone
#endif
// Note the id of a crate we caused to be created.
ObjectID m_crateCreated;
Int m_tmpInt;
// -------------------------------------------------------------------
Bool m_doFinalPosition; ///< True if we are moving towards final position in a non-physics kind of way.
Bool m_waitingForPath; ///< True if we have a pathfind request outstanding.
Bool m_isAttackPath; ///< True if we have an attack path.
Bool m_isFinalGoal; ///< True if this path ends at our destination (as opposed to an intermediate point on a waypoint path).
Bool m_isApproachPath; ///< True if we are just approaching to tighten.
Bool m_isSafePath; ///< True if we are just approaching to tighten.
Bool m_movementComplete; ///< True if we finished an AIInternalMoveToState.
Bool m_isMoving; ///< True if we are in an AIInternalMoveToState.
Bool m_isBlocked;
Bool m_isBlockedAndStuck; ///< True if we are stuck & need to recompute path.
Bool m_upgradedLocomotors;
Bool m_canPathThroughUnits; ///< Can path through units.
Bool m_randomlyOffsetMoodCheck; ///< If true, randomly offset the mood check rate next time, to avoid "spiking" of ai checks
Bool m_isAiDead; ///< TRUE if dead
Bool m_isRecruitable; ///< TRUE if recruitable by the ai.
Bool m_executingWaypointQueue; ///< if true, we are moving thru the waypoints
Bool m_retryPath; ///< If true, we need to try the path a second time. jba.
Bool m_allowedToChase; ///< Allowed to pursue targets.
Bool m_isInUpdate; ///< If true, we are inside our update method.
Bool m_fixLocoInPostProcess;
};
//------------------------------------------------------------------------------------------------------------
// Inlines
//
#endif // _AI_UPDATE_H_

View file

@ -0,0 +1,179 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ActiveBody.h /////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, November 2001
// Desc: Active bodies have health, they can die and are affected by health
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __ACTIVEBODY_H_
#define __ACTIVEBODY_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/DamageFX.h"
#include "GameLogic/Module/BodyModule.h"
#include "GameLogic/Damage.h"
#include "GameLogic/Armor.h"
#include "GameLogic/ArmorSet.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class BodyParticleSystem;
class ParticleSystemTemplate;
//-------------------------------------------------------------------------------------------------
/** Active body module */
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class ActiveBodyModuleData : public BodyModuleData
{
public:
Real m_maxHealth;
Real m_initialHealth;
Real m_subdualDamageCap; ///< Subdual damage will never accumulate past this
UnsignedInt m_subdualDamageHealRate; ///< Every this often, we drop subdual damage...
Real m_subdualDamageHealAmount; ///< by this much.
ActiveBodyModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
class ActiveBody : public BodyModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ActiveBody, "ActiveBody" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( ActiveBody, ActiveBodyModuleData )
public:
ActiveBody( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onDelete( void );
virtual void attemptDamage( DamageInfo *damageInfo ); ///< try to damage this object
virtual Real estimateDamage( DamageInfoInput& damageInfo ) const;
virtual void attemptHealing( DamageInfo *damageInfo ); ///< try to heal this object
virtual Real getHealth() const; ///< get current health
virtual BodyDamageType getDamageState() const;
virtual void setDamageState( BodyDamageType newState ); ///< control damage state directly. Will adjust hitpoints.
virtual void setAflame( Bool setting );///< This is a major change like a damage state.
virtual UnsignedInt getSubdualDamageHealRate() const;
virtual Real getSubdualDamageHealAmount() const;
virtual Bool hasAnySubdualDamage() const;
virtual Real getCurrentSubdualDamageAmount() const { return m_currentSubdualDamage; }
virtual const DamageInfo *getLastDamageInfo() const { return &m_lastDamageInfo; } ///< return info on last damage dealt to this object
virtual UnsignedInt getLastDamageTimestamp() const { return m_lastDamageTimestamp; } ///< return frame of last damage dealt
virtual UnsignedInt getLastHealingTimestamp() const { return m_lastHealingTimestamp; } ///< return frame of last damage dealt
virtual ObjectID getClearableLastAttacker() const { return (m_lastDamageCleared ? INVALID_ID : m_lastDamageInfo.in.m_sourceID); }
virtual void clearLastAttacker() { m_lastDamageCleared = true; }
void onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback = TRUE );
virtual void setArmorSetFlag(ArmorSetType ast) { m_curArmorSetFlags.set(ast, 1); }
virtual void clearArmorSetFlag(ArmorSetType ast) { m_curArmorSetFlags.set(ast, 0); }
virtual Bool testArmorSetFlag(ArmorSetType ast) { return m_curArmorSetFlags.test(ast); }
virtual void setInitialHealth(Int initialPercent); ///< Sets the inital load health %.
virtual void setMaxHealth( Real maxHealth, MaxHealthChangeType healthChangeType = SAME_CURRENTHEALTH ); ///< Sets the inital max health
virtual Bool getFrontCrushed() const { return m_frontCrushed; }
virtual Bool getBackCrushed() const { return m_backCrushed; }
virtual void setFrontCrushed(Bool v) { m_frontCrushed = v; }
virtual void setBackCrushed(Bool v) { m_backCrushed = v; }
virtual Real getMaxHealth() const; ///< return max health
virtual Real getInitialHealth() const; // return initial health
virtual Real getPreviousHealth() const { return m_prevHealth; }
virtual void setIndestructible( Bool indestructible );
virtual Bool isIndestructible( void ) const { return m_indestructible; }
virtual void internalChangeHealth( Real delta ); ///< change health
virtual void evaluateVisualCondition();
virtual void updateBodyParticleSystems( void );// made public for topple anf building collapse updates -ML
// Subdual Damage
virtual Bool isSubdued() const;
virtual Bool canBeSubdued() const;
virtual void onSubdualChange( Bool isNowSubdued );///< Override this if you want a totally different effect than DISABLED_SUBDUED
protected:
void validateArmorAndDamageFX() const;
void doDamageFX( const DamageInfo *damageInfo );
void createParticleSystems( const AsciiString &boneBaseName,
const ParticleSystemTemplate *systemTemplate,
Int maxSystems );
void deleteAllParticleSystems( void );
void setCorrectDamageState();
Bool shouldRetaliate(Object *obj);
Bool shouldRetaliateAgainstAggressor(Object *obj, Object *damager);
virtual void internalAddSubdualDamage( Real delta ); ///< change health
private:
Real m_currentHealth; ///< health of the object
Real m_prevHealth; ///< previous health value before current health change op
Real m_maxHealth; ///< max health this object can have
Real m_initialHealth; ///< starting health for this object
Real m_currentSubdualDamage; ///< Starts at zero and goes up. Inherited modules will do something when "subdued".
BodyDamageType m_curDamageState; ///< last known damage state
UnsignedInt m_nextDamageFXTime;
DamageType m_lastDamageFXDone;
DamageInfo m_lastDamageInfo; ///< store the last DamageInfo object that we received
UnsignedInt m_lastDamageTimestamp; ///< frame of last damage dealt
UnsignedInt m_lastHealingTimestamp; ///< frame of last healing dealt
Bool m_frontCrushed;
Bool m_backCrushed;
Bool m_lastDamageCleared;
Bool m_indestructible; ///< is this object indestructible?
BodyParticleSystem *m_particleSystems; ///< particle systems created and attached to this object
/*
Note, you MUST call validateArmorAndDamageFX() before accessing these fields.
*/
ArmorSetFlags m_curArmorSetFlags;
mutable const ArmorTemplateSet* m_curArmorSet;
mutable Armor m_curArmor;
mutable const DamageFX* m_curDamageFX;
};
#endif // __ACTIVEBODY_H_

View file

@ -0,0 +1,80 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ActiveShroudUpgrade.h ///////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, July 2002
// Desc: An upgrade that modifies the object's ShroudRange.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __ACTIVE_SHROUD_UPGRADE_H_
#define __ACTIVE_SHROUD_UPGRADE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpgradeModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class Player;
class ObjectCreationList;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class ActiveShroudUpgradeModuleData : public UpgradeModuleData
{
public:
ActiveShroudUpgradeModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p);
Real m_newShroudRange;
};
//-------------------------------------------------------------------------------------------------
/** An upgrade that modifies the object's ShroudRange */
//-------------------------------------------------------------------------------------------------
class ActiveShroudUpgrade : public UpgradeModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ActiveShroudUpgrade, "ActiveShroudUpgrade" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( ActiveShroudUpgrade, ActiveShroudUpgradeModuleData );
public:
ActiveShroudUpgrade( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
protected:
virtual void upgradeImplementation( void ); ///< Here's the actual work of Upgrading
virtual Bool isSubObjectsUpgrade() { return false; }
};
#endif // __ACTIVE_SHROUD_UPGRADE_H_

View file

@ -0,0 +1,87 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AnimationSteeringUpdate.h ////////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, April 2002
// Desc: Uses animation states to handle steering.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __ANIMATION_STEERING_UPDATE_H
#define __ANIMATION_STEERING_UPDATE_H
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
enum PhysicsTurningType;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class AnimationSteeringUpdateModuleData : public UpdateModuleData
{
public:
AnimationSteeringUpdateModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse( p );
static const FieldParse dataFieldParse[] =
{
{ "MinTransitionTime", INI::parseDurationUnsignedInt, NULL, offsetof( AnimationSteeringUpdateModuleData, m_transitionFrames ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
UnsignedInt m_transitionFrames;
};
//-------------------------------------------------------------------------------------------------
/** The AnimationSteering Update module */
//-------------------------------------------------------------------------------------------------
class AnimationSteeringUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AnimationSteeringUpdate, "AnimationSteeringUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AnimationSteeringUpdate, AnimationSteeringUpdateModuleData );
public:
AnimationSteeringUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
virtual UpdateSleepTime update( void ); ///< Here's the actual work of Upgrading
protected:
ModelConditionFlagType m_currentTurnAnim;
UnsignedInt m_nextTransitionFrame;
};
#endif // end __ANIMATION_STEERING_UPDATE_H

View file

@ -0,0 +1,94 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ArmorUpgrade.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// created: July 2002
//
// Filename: ArmorUpgrade.h
//
// author: Chris Brue
//
// purpose:
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __ARMOR_UPGRADE_H_
#define __ARMOR_UPGRADE_H_
//-----------------------------------------------------------------------------
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "GameLogic/Module/UpgradeModule.h"
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
class Thing;
//-----------------------------------------------------------------------------
// TYPE DEFINES ///////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
class ArmorUpgrade : public UpgradeModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ArmorUpgrade, "ArmorUpgrade" )
MAKE_STANDARD_MODULE_MACRO( ArmorUpgrade );
public:
ArmorUpgrade( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
protected:
virtual void upgradeImplementation( ); ///< Here's the actual work of Upgrading
virtual Bool isSubObjectsUpgrade() { return false; }
};
//-----------------------------------------------------------------------------
// INLINING ///////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// EXTERNALS //////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#endif // __ARMOR_UPGRADE_H_

View file

@ -0,0 +1,128 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// AssaultTransportAIUpdate.h ////////////
// Author: Kris Morness, December 2002
// Desc: State machine that allows assault transports (troop crawler) to deploy
// troops, order them to attack, then return. Can do extra things like ordering
// injured troops to return to the transport for healing purposes.
#pragma once
#ifndef __ASSAULT_TRANSPORT_AI_UPDATE_H
#define __ASSAULT_TRANSPORT_AI_UPDATE_H
#include "Common/StateMachine.h"
#include "GameLogic/Module/AIUpdate.h"
//-------------------------------------------------------------------------------------------------
enum AssaultStateTypes
{
IDLE, ///< Not doing anything.
ASSAULTING, ///< Transport is waiting while troops do fighting.
};
#define MAX_TRANSPORT_SLOTS 10
//-------------------------------------------------------------------------------------------------
class AssaultTransportAIUpdateModuleData : public AIUpdateModuleData
{
public:
Real m_membersGetHealedAtLifeRatio;
Real m_clearRangeRequiredToContinueAttackMove;
AssaultTransportAIUpdateModuleData()
{
m_membersGetHealedAtLifeRatio = 0.0f;
m_clearRangeRequiredToContinueAttackMove = 50.0f;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
AIUpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "MembersGetHealedAtLifeRatio", INI::parseReal, NULL, offsetof( AssaultTransportAIUpdateModuleData, m_membersGetHealedAtLifeRatio ) },
{ "ClearRangeRequiredToContinueAttackMove", INI::parseReal, NULL, offsetof( AssaultTransportAIUpdateModuleData, m_clearRangeRequiredToContinueAttackMove ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
class AssaultTransportAIInterface
{
public:
virtual void beginAssault( const Object *designatedTarget ) const = 0;
};
//-------------------------------------------------------------------------------------------------
class AssaultTransportAIUpdate : public AIUpdateInterface, public AssaultTransportAIInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AssaultTransportAIUpdate, "AssaultTransportAIUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AssaultTransportAIUpdate, AssaultTransportAIUpdateModuleData )
private:
public:
AssaultTransportAIUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void aiDoCommand(const AICommandParms* parms);
virtual Bool isIdle() const;
virtual UpdateSleepTime update();
virtual AssaultTransportAIInterface* getAssaultTransportAIInterface() { return this; }
virtual const AssaultTransportAIInterface* getAssaultTransportAIInterface() const { return this; }
virtual void beginAssault( const Object *designatedTarget ) const;
UpdateSleepTime calcSleepTime();
void reset();
Bool isMemberWounded( const Object *member ) const; //Member requires medical attention?
Bool isMemberHealthy( const Object *member ) const; //Member has full health?
void retrieveMembers();
void giveFinalOrders();
Bool isAttackPointless() const;
protected:
ObjectID m_memberIDs[ MAX_TRANSPORT_SLOTS ];
Bool m_memberHealing[ MAX_TRANSPORT_SLOTS ];
Bool m_newMember[ MAX_TRANSPORT_SLOTS ];
Coord3D m_attackMoveGoalPos;
mutable ObjectID m_designatedTarget;
AssaultStateTypes m_state;
UnsignedInt m_framesRemaining;
Int m_currentMembers;
Bool m_isAttackMove;
Bool m_isAttackObject;
Bool m_newOccupantsAreNewMembers;
};
#endif

View file

@ -0,0 +1,87 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AssistedTargetingUpdate.h /////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, September 2002
// Desc: Outside influences can tell me to attack something out of my normal targeting range
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _ASSISTED_TARGETING_UPDATE_H
#define _ASSISTED_TARGETING_UPDATE_H
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
//-------------------------------------------------------------------------------------------------
class AssistedTargetingUpdateModuleData : public UpdateModuleData
{
public:
Int m_clipSize;
WeaponSlotType m_weaponSlot;
AsciiString m_laserFromAssistedName;
AsciiString m_laserToTargetName;
AssistedTargetingUpdateModuleData()
{
m_clipSize = 1;
m_weaponSlot = PRIMARY_WEAPON;
m_laserFromAssistedName.clear();
m_laserToTargetName.clear();
}
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class AssistedTargetingUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AssistedTargetingUpdate, "AssistedTargetingUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AssistedTargetingUpdate, AssistedTargetingUpdateModuleData )
public:
AssistedTargetingUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update( void );
Bool isFreeToAssist() const;
void assistAttack( const Object *requestingObject, Object *victimObject );
private:
void makeFeedbackLaser( const ThingTemplate *laserTemplate, const Object *from, const Object *to );
const ThingTemplate *m_laserFromAssisted;
const ThingTemplate *m_laserToTarget;
};
#endif

View file

@ -0,0 +1,144 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AutoDepositUpdate.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// created: Aug 2002
//
// Filename: AutoDepositUpdate.h
//
// author: Chris Huybregts
//
// purpose: Auto Deposit Update Module
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __AUTO_DEPOSIT_UPDATE_H_
#define __AUTO_DEPOSIT_UPDATE_H_
//-----------------------------------------------------------------------------
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "GameLogic/Module/UpdateModule.h"
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
class Player;
class Thing;
void parseUpgradePair( INI *ini, void *instance, void *store, const void *userData );
struct upgradePair
{
std::string type;
Int amount;
};
//-----------------------------------------------------------------------------
// TYPE DEFINES ///////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
class AutoDepositUpdateModuleData : public UpdateModuleData
{
public:
UnsignedInt m_depositFrame;
Int m_depositAmount;
Int m_initialCaptureBonus;
Bool m_isActualMoney;
std::list<upgradePair> m_upgradeBoost;
AutoDepositUpdateModuleData()
{
m_depositFrame = 0;
m_depositAmount = 0;
m_initialCaptureBonus = 0;
m_isActualMoney = TRUE;
m_upgradeBoost.clear();
}
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "DepositTiming", INI::parseDurationUnsignedInt, NULL, offsetof( AutoDepositUpdateModuleData, m_depositFrame ) },
{ "DepositAmount", INI::parseInt, NULL, offsetof( AutoDepositUpdateModuleData, m_depositAmount ) },
{ "InitialCaptureBonus", INI::parseInt, NULL, offsetof( AutoDepositUpdateModuleData, m_initialCaptureBonus ) },
{ "ActualMoney", INI::parseBool, NULL, offsetof( AutoDepositUpdateModuleData, m_isActualMoney ) },
{ "UpgradedBoost", parseUpgradePair, NULL, offsetof( AutoDepositUpdateModuleData, m_upgradeBoost ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
class AutoDepositUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AutoDepositUpdate, "AutoDepositUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AutoDepositUpdate, AutoDepositUpdateModuleData )
public:
AutoDepositUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
void awardInitialCaptureBonus( Player *player ); // Test and award the initial capture bonus
virtual UpdateSleepTime update( void );
protected:
Int getUpgradedSupplyBoost() const;
UnsignedInt m_depositOnFrame;
Bool m_awardInitialCaptureBonus;
Bool m_initialized;
};
//-----------------------------------------------------------------------------
// INLINING ///////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// EXTERNALS //////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#endif // __AUTO_DEPOSIT_UPDATE_H_

View file

@ -0,0 +1,86 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AutoFindHealingUpdate.cpp //////////////////////////////////////////////////////////////////////////
// Author: John Ahlquist, Sept. 2002
// Desc: Update module to handle wounded idle infantry finding a heal unit or structure.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __AUTO_FIND_HEALING_UPDATE_H_
#define __AUTO_FIND_HEALING_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/KindOf.h"
#include "GameLogic/Module/UpdateModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class ThingTemplate;
class WeaponTemplate;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class AutoFindHealingUpdateModuleData : public ModuleData
{
public:
UnsignedInt m_scanFrames;
Real m_scanRange;
Real m_neverHeal;
Real m_alwaysHeal;
AutoFindHealingUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
/** The default update module */
//-------------------------------------------------------------------------------------------------
class AutoFindHealingUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AutoFindHealingUpdate, "AutoFindHealingUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AutoFindHealingUpdate, AutoFindHealingUpdateModuleData );
public:
AutoFindHealingUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onObjectCreated();
virtual UpdateSleepTime update();
Object* scanClosestTarget();
protected:
Int m_nextScanFrames;
};
#endif

View file

@ -0,0 +1,194 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AutoHealBehavior.h /////////////////////////////////////////////////////////////////////////
// Author: Colin Day, December 2001
// Desc: Update that heals itself
//------------------------------------------
// Modified by Kris Morness, September 2002
// Kris: Added the ability to add effects, radius healing, and restricting the type of objects
// subjected to the heal (or repair).
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __AutoHealBehavior_H_
#define __AutoHealBehavior_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameClient/ParticleSys.h"
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/UpgradeModule.h"
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Module/DamageModule.h"
#include "Common/BitFlagsIO.h"
class ParticleSystem;
class ParticleSystemTemplate;
//-------------------------------------------------------------------------------------------------
class AutoHealBehaviorModuleData : public UpdateModuleData
{
public:
UpgradeMuxData m_upgradeMuxData;
Bool m_initiallyActive;
Bool m_singleBurst;
Int m_healingAmount;
UnsignedInt m_healingDelay;
UnsignedInt m_startHealingDelay; ///< how long since our last damage till autoheal starts.
Real m_radius; //If non-zero, then it becomes a area effect.
Bool m_affectsWholePlayer; ///< I have more than a range, I try to affect everything the player owns
Bool m_skipSelfForHealing; ///< Don't heal myself.
KindOfMaskType m_kindOf; //Only these types can heal -- defaults to everything.
KindOfMaskType m_forbiddenKindOf; //Only these types can heal -- defaults to everything.
const ParticleSystemTemplate* m_radiusParticleSystemTmpl; //Optional particle system meant to apply to entire effect for entire duration.
const ParticleSystemTemplate* m_unitHealPulseParticleSystemTmpl; //Optional particle system applying to each object getting healed each heal pulse.
AutoHealBehaviorModuleData()
{
m_initiallyActive = false;
m_singleBurst = FALSE;
m_healingAmount = 0;
m_healingDelay = UINT_MAX;
m_startHealingDelay = 0;
m_radius = 0.0f;
m_radiusParticleSystemTmpl = NULL;
m_unitHealPulseParticleSystemTmpl = NULL;
m_affectsWholePlayer = FALSE;
m_skipSelfForHealing = FALSE;
SET_ALL_KINDOFMASK_BITS( m_kindOf );
m_forbiddenKindOf.clear();
}
static void buildFieldParse(MultiIniFieldParse& p)
{
static const FieldParse dataFieldParse[] =
{
{ "StartsActive", INI::parseBool, NULL, offsetof( AutoHealBehaviorModuleData, m_initiallyActive ) },
{ "SingleBurst", INI::parseBool, NULL, offsetof( AutoHealBehaviorModuleData, m_singleBurst ) },
{ "HealingAmount", INI::parseInt, NULL, offsetof( AutoHealBehaviorModuleData, m_healingAmount ) },
{ "HealingDelay", INI::parseDurationUnsignedInt, NULL, offsetof( AutoHealBehaviorModuleData, m_healingDelay ) },
{ "Radius", INI::parseReal, NULL, offsetof( AutoHealBehaviorModuleData, m_radius ) },
{ "KindOf", KindOfMaskType::parseFromINI, NULL, offsetof( AutoHealBehaviorModuleData, m_kindOf ) },
{ "ForbiddenKindOf", KindOfMaskType::parseFromINI, NULL, offsetof( AutoHealBehaviorModuleData, m_forbiddenKindOf ) },
{ "RadiusParticleSystemName", INI::parseParticleSystemTemplate, NULL, offsetof( AutoHealBehaviorModuleData, m_radiusParticleSystemTmpl ) },
{ "UnitHealPulseParticleSystemName", INI::parseParticleSystemTemplate, NULL, offsetof( AutoHealBehaviorModuleData, m_unitHealPulseParticleSystemTmpl ) },
{ "StartHealingDelay", INI::parseDurationUnsignedInt, NULL, offsetof( AutoHealBehaviorModuleData, m_startHealingDelay ) },
{ "AffectsWholePlayer", INI::parseBool, NULL, offsetof( AutoHealBehaviorModuleData, m_affectsWholePlayer ) },
{ "SkipSelfForHealing", INI::parseBool, NULL, offsetof( AutoHealBehaviorModuleData, m_skipSelfForHealing ) },
{ 0, 0, 0, 0 }
};
UpdateModuleData::buildFieldParse(p);
p.add(dataFieldParse);
p.add(UpgradeMuxData::getFieldParse(), offsetof( AutoHealBehaviorModuleData, m_upgradeMuxData ));
}
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class AutoHealBehavior : public UpdateModule,
public UpgradeMux,
public DamageModuleInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AutoHealBehavior, "AutoHealBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AutoHealBehavior, AutoHealBehaviorModuleData )
public:
AutoHealBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// module methods
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | MODULEINTERFACE_UPGRADE | MODULEINTERFACE_DAMAGE; }
// BehaviorModule
virtual UpgradeModuleInterface* getUpgrade() { return this; }
virtual DamageModuleInterface* getDamage() { return this; }
// DamageModuleInterface
virtual void onDamage( DamageInfo *damageInfo );
virtual void onHealing( DamageInfo *damageInfo ) { }
virtual void onBodyDamageStateChange(const DamageInfo* damageInfo, BodyDamageType oldState, BodyDamageType newState) { }
// UpdateModuleInterface
virtual UpdateSleepTime update();
virtual DisabledMaskType getDisabledTypesToProcess() const { return MAKE_DISABLED_MASK( DISABLED_HELD ); }
void stopHealing();
void undoUpgrade(); ///<pretend like we have not been activated yet, so we can be reactivated later
protected:
virtual void upgradeImplementation()
{
setWakeFrame(getObject(), UPDATE_SLEEP_NONE);
}
virtual void getUpgradeActivationMasks(UpgradeMaskType& activation, UpgradeMaskType& conflicting) const
{
getAutoHealBehaviorModuleData()->m_upgradeMuxData.getUpgradeActivationMasks(activation, conflicting);
}
virtual void performUpgradeFX()
{
getAutoHealBehaviorModuleData()->m_upgradeMuxData.performUpgradeFX(getObject());
}
virtual void processUpgradeRemoval()
{
// I can't take it any more. Let the record show that I think the UpgradeMux multiple inheritence is CRAP.
getAutoHealBehaviorModuleData()->m_upgradeMuxData.muxDataProcessUpgradeRemoval(getObject());
}
virtual Bool requiresAllActivationUpgrades() const
{
return getAutoHealBehaviorModuleData()->m_upgradeMuxData.m_requiresAllTriggers;
}
inline Bool isUpgradeActive() const { return isAlreadyUpgraded(); }
virtual Bool isSubObjectsUpgrade() { return false; }
private:
void pulseHealObject( Object *obj );
ParticleSystemID m_radiusParticleSystemID;
UnsignedInt m_soonestHealFrame;/** I need to record this, because with multiple wake up sources,
I can't rely solely on my sleeping. So this will guard onDamage's wake up.
I could guard the act of healing, but that would defeat the gain of being
a sleepy module. I never want to run update unless I am going to heal.
*/
Bool m_stopped;
};
#endif // __AutoHealBehavior_H_

View file

@ -0,0 +1,89 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BaikonurLaunchPower.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Created: November 2002
//
// Filename: BaikonurLaunchPower.h
//
// Author: Kris Morness
//
// Purpose: Triggers the beginning of the launch for the baikonur launch tower.
// This is used only by script to trigger the GLA end game.
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BAIKONUR_LAUNCH_POWER_H_
#define __BAIKONUR_LAUNCH_POWER_H_
#include "GameLogic/Module/SpecialPowerModule.h"
class Object;
class SpecialPowerTemplate;
struct FieldParse;
enum ScienceType;
class BaikonurLaunchPowerModuleData : public SpecialPowerModuleData
{
public:
BaikonurLaunchPowerModuleData( void );
static void buildFieldParse( MultiIniFieldParse& p );
AsciiString m_detonationObject;
};
//-------------------------------------------------------------------------------------------------
class BaikonurLaunchPower : public SpecialPowerModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BaikonurLaunchPower, "BaikonurLaunchPower" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( BaikonurLaunchPower, BaikonurLaunchPowerModuleData )
public:
BaikonurLaunchPower( Thing *thing, const ModuleData *moduleData );
virtual void doSpecialPower( UnsignedInt commandOptions );
virtual void doSpecialPowerAtLocation( const Coord3D *loc, Real angle, UnsignedInt commandOptions );
protected:
};
#endif // __BAIKONUR_LAUNCH_POWER_H_

View file

@ -0,0 +1,85 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BaseRegenerateUpdate.h ///////////////////////////////////////////////////////////////////
// Author: Colin Day, July 2002
// Desc: Update module for base objects automatically regenerating health
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BASE_REGENERATE_UPDATE_H_
#define __BASE_REGENERATE_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Module/DamageModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BaseRegenerateUpdateModuleData : public UpdateModuleData
{
public:
BaseRegenerateUpdateModuleData( void );
static void buildFieldParse( MultiIniFieldParse &p );
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BaseRegenerateUpdate : public UpdateModule,
public DamageModuleInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BaseRegenerateUpdate, "BaseRegenerateUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( BaseRegenerateUpdate, BaseRegenerateUpdateModuleData );
public:
BaseRegenerateUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | MODULEINTERFACE_DAMAGE; }
// BehaviorModule
virtual DamageModuleInterface* getDamage() { return this; }
// UpdateModuleInterface
virtual UpdateSleepTime update( void );
// DamageModuleInterface
virtual void onDamage( DamageInfo *damageInfo );
virtual void onHealing( DamageInfo *damageInfo ) { }
virtual void onBodyDamageStateChange(const DamageInfo* damageInfo, BodyDamageType oldState, BodyDamageType newState) { }
virtual DisabledMaskType getDisabledTypesToProcess() const { return MAKE_DISABLED_MASK( DISABLED_UNDERPOWERED ); }
private:
};
#endif // end __BASE_REGENERATE_UPDATE_H_

View file

@ -0,0 +1,93 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BattleBusSlowDeathBehavior.h ///////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, June 2003
// Desc: Death for the Battle Bus. Can do a fake slow death before the real one if triggered intentionally
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BUS_SLOW_DEATH_BEHAVIOR_H_
#define __BUS_SLOW_DEATH_BEHAVIOR_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/SlowDeathBehavior.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class FXList;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class BattleBusSlowDeathBehaviorModuleData : public SlowDeathBehaviorModuleData
{
public:
BattleBusSlowDeathBehaviorModuleData( void );
static void buildFieldParse( MultiIniFieldParse &p );
const FXList *m_fxStartUndeath; ///< fx list executed on start of throw
const ObjectCreationList *m_oclStartUndeath; ///< ocl list executed on start of throw
const FXList *m_fxHitGround; ///< FXList for when we land
const ObjectCreationList *m_oclHitGround; ///< OCL for when we land
Real m_throwForce; ///< How hard we are thrown in to the air
Real m_percentDamageToPassengers; ///< At the moment we throw up, how hard the people inside are hit
UnsignedInt m_emptyHulkDestructionDelay; ///< Another reason this is a BattleBus module, and not a generic two stage death. If non-zero, time empty before we kill ourselves.
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BattleBusSlowDeathBehavior : public SlowDeathBehavior
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BattleBusSlowDeathBehavior, "BattleBusSlowDeathBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( BattleBusSlowDeathBehavior, BattleBusSlowDeathBehaviorModuleData )
public:
BattleBusSlowDeathBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// slow death methods
virtual void onDie( const DamageInfo *damageInfo );
virtual void beginSlowDeath( const DamageInfo *damageInfo );
virtual UpdateSleepTime update( void );
protected:
Bool m_isRealDeath; ///< Flag set by onDie that prevents the alternate processing caused by beginSlowDeath.
Bool m_isInFirstDeath; ///< Flag that controls lifetime of alternate processing. Prevented by RealDeath flag.
UnsignedInt m_groundCheckFrame; ///< Don't check for bouncing until at least here.
UnsignedInt m_penaltyDeathFrame; ///< If non zero, kill us with Penalty damage at this frame
};
#endif // end __BUS_SLOW_DEATH_BEHAVIOR_H_

View file

@ -0,0 +1,196 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BattlePlanUpdate.h //////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, September 2002
// Desc: Update module to handle building states and battle plan execution & changes
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BATTLE_PLAN_UPDATE_H_
#define __BATTLE_PLAN_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/KindOf.h"
#include "GameLogic/Module/SpecialPowerUpdateModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class SpecialPowerModule;
class ParticleSystem;
class FXList;
class AudioEventRTS;
enum MaxHealthChangeType;
enum CommandOption;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class BattlePlanUpdateModuleData : public ModuleData
{
public:
SpecialPowerTemplate *m_specialPowerTemplate;
UnsignedInt m_bombardmentPlanAnimationFrames;
UnsignedInt m_holdTheLinePlanAnimationFrames;
UnsignedInt m_searchAndDestroyPlanAnimationFrames;
UnsignedInt m_transitionIdleFrames;
AsciiString m_bombardmentUnpackName;
AsciiString m_bombardmentPackName;
AsciiString m_bombardmentMessageLabel;
AsciiString m_bombardmentAnnouncementName;
AsciiString m_searchAndDestroyUnpackName;
AsciiString m_searchAndDestroyIdleName;
AsciiString m_searchAndDestroyPackName;
AsciiString m_searchAndDestroyMessageLabel;
AsciiString m_searchAndDestroyAnnouncementName;
AsciiString m_holdTheLineUnpackName;
AsciiString m_holdTheLinePackName;
AsciiString m_holdTheLineMessageLabel;
AsciiString m_holdTheLineAnnouncementName;
UnsignedInt m_battlePlanParalyzeFrames;
KindOfMaskType m_validMemberKindOf;
KindOfMaskType m_invalidMemberKindOf;
Real m_holdTheLineArmorDamageScalar;
Real m_searchAndDestroySightRangeScalar;
Real m_strategyCenterSearchAndDestroySightRangeScalar;
Bool m_strategyCenterSearchAndDestroyDetectsStealth;
Real m_strategyCenterHoldTheLineMaxHealthScalar;
MaxHealthChangeType m_strategyCenterHoldTheLineMaxHealthChangeType;
AsciiString m_visionObjectName; ///< name of object to create to reveal shroud to all players
BattlePlanUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
enum TransitionStatus
{
TRANSITIONSTATUS_IDLE,
TRANSITIONSTATUS_UNPACKING,
TRANSITIONSTATUS_ACTIVE,
TRANSITIONSTATUS_PACKING,
};
enum BattlePlanStatus
{
PLANSTATUS_NONE,
PLANSTATUS_BOMBARDMENT,
PLANSTATUS_HOLDTHELINE,
PLANSTATUS_SEARCHANDDESTROY,
};
class BattlePlanBonuses : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(BattlePlanBonuses, "BattlePlanBonuses")
public:
Real m_armorScalar;
Int m_bombardment; //Represents having weapon bonuses for bombardment plan
Int m_searchAndDestroy; //Represents having weapon bonuses for searchAndDestroy plan
Int m_holdTheLine; //Represents having weapon bonuses for holdTheLine plan
Real m_sightRangeScalar;
KindOfMaskType m_validKindOf;
KindOfMaskType m_invalidKindOf;
};
EMPTY_DTOR(BattlePlanBonuses)
#define ALL_PLANS 1000000 //Used when stacking or removing plans -- we only remove the bonuses when it's 0 or negative.
//-------------------------------------------------------------------------------------------------
/** The default update module */
//-------------------------------------------------------------------------------------------------
class BattlePlanUpdate : public SpecialPowerUpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BattlePlanUpdate, "BattlePlanUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( BattlePlanUpdate, BattlePlanUpdateModuleData );
public:
BattlePlanUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// SpecialPowerUpdateInterface
virtual Bool initiateIntentToDoSpecialPower(const SpecialPowerTemplate *specialPowerTemplate, const Object *targetObj, const Coord3D *targetPos, const Waypoint *way, UnsignedInt commandOptions );
virtual Bool isSpecialAbility() const { return false; }
virtual Bool isSpecialPower() const { return true; }
virtual Bool isActive() const {return m_status != TRANSITIONSTATUS_IDLE;}
virtual SpecialPowerUpdateInterface* getSpecialPowerUpdateInterface() { return this; }
virtual Bool doesSpecialPowerHaveOverridableDestinationActive() const { return false; } //Is it active now?
virtual Bool doesSpecialPowerHaveOverridableDestination() const { return false; } //Does it have it, even if it's not active?
virtual void setSpecialPowerOverridableDestination( const Coord3D *loc ) {}
virtual Bool isPowerCurrentlyInUse( const CommandButton *command = NULL ) const;
//Returns the currently active battle plan -- unpacked and ready... returns PLANSTATUS_NONE if in transition!
BattlePlanStatus getActiveBattlePlan() const;
virtual void onObjectCreated();
virtual void onDelete();
virtual UpdateSleepTime update();
virtual CommandOption getCommandOption() const;
protected:
void setStatus( TransitionStatus status );
void enableTurret( Bool enable );
void recenterTurret();
Bool isTurretInNaturalPosition();
void setBattlePlan( BattlePlanStatus plan );
void createVisionObject();
BattlePlanStatus m_currentPlan; //The current battle plan displayed by the building (includes packing & unpacking)
BattlePlanStatus m_desiredPlan; //The user desired battle plan
BattlePlanStatus m_planAffectingArmy; //The current battle plan that is affecting troops!
TransitionStatus m_status;
UnsignedInt m_nextReadyFrame;
SpecialPowerModuleInterface *m_specialPowerModule;
Bool m_invalidSettings;
Bool m_centeringTurret;
BattlePlanBonuses* m_bonuses;
AudioEventRTS m_bombardmentUnpack;
AudioEventRTS m_bombardmentPack;
AudioEventRTS m_bombardmentAnnouncement;
AudioEventRTS m_searchAndDestroyUnpack;
AudioEventRTS m_searchAndDestroyIdle;
AudioEventRTS m_searchAndDestroyPack;
AudioEventRTS m_searchAndDestroyAnnouncement;
AudioEventRTS m_holdTheLineUnpack;
AudioEventRTS m_holdTheLinePack;
AudioEventRTS m_holdTheLineAnnouncement;
// vision object - hang on to this so we can delete it on destruction
ObjectID m_visionObjectID;
};
#endif

View file

@ -0,0 +1,283 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BehaviorModule.h /////////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BehaviorModule_H_
#define __BehaviorModule_H_
#include "Common/GameType.h"
#include "Common/Module.h"
//-------------------------------------------------------------------------------------------------
class Team;
class ThingTemplate;
//-------------------------------------------------------------------------------------------------
class BodyModuleInterface;
class CollideModuleInterface;
class ContainModuleInterface;
class CreateModuleInterface;
class DamageModuleInterface;
class DestroyModuleInterface;
class DieModuleInterface;
class SpecialPowerModuleInterface;
class UpdateModuleInterface;
class UpgradeModuleInterface;
//-------------------------------------------------------------------------------------------------
class ParkingPlaceBehaviorInterface;
class RebuildHoleBehaviorInterface;
class BridgeBehaviorInterface;
class BridgeTowerBehaviorInterface;
class BridgeScaffoldBehaviorInterface;
class OverchargeBehaviorInterface;
class TransportPassengerInterface;
class CaveInterface;
class LandMineInterface;
class ProjectileUpdateInterface;
class AIUpdateInterface;
class ExitInterface;
class DockUpdateInterface;
class RailedTransportDockUpdateInterface;
class SpecialPowerUpdateInterface;
class SlavedUpdateInterface;
class SpawnBehaviorInterface;
class CountermeasuresBehaviorInterface;
class SlowDeathBehaviorInterface;
class PowerPlantUpdateInterface;
class ProductionUpdateInterface;
class HordeUpdateInterface;
class SpecialPowerTemplate;
class WeaponTemplate;
class DamageInfo;
class ParticleSystemTemplate;
class StealthUpdate;
class SpyVisionUpdate;
//-------------------------------------------------------------------------------------------------
class BehaviorModuleData : public ModuleData
{
public:
BehaviorModuleData()
{
}
static void buildFieldParse(MultiIniFieldParse& p)
{
ModuleData::buildFieldParse(p);
}
};
//-------------------------------------------------------------------------------------------------
class BehaviorModuleInterface
{
public:
virtual BodyModuleInterface* getBody() = 0;
virtual CollideModuleInterface* getCollide() = 0;
virtual ContainModuleInterface* getContain() = 0;
virtual CreateModuleInterface* getCreate() = 0;
virtual DamageModuleInterface* getDamage() = 0;
virtual DestroyModuleInterface* getDestroy() = 0;
virtual DieModuleInterface* getDie() = 0;
virtual SpecialPowerModuleInterface* getSpecialPower() = 0;
virtual UpdateModuleInterface* getUpdate() = 0;
virtual UpgradeModuleInterface* getUpgrade() = 0;
// interface acquisition
virtual ParkingPlaceBehaviorInterface* getParkingPlaceBehaviorInterface() = 0;
virtual RebuildHoleBehaviorInterface* getRebuildHoleBehaviorInterface() = 0;
virtual BridgeBehaviorInterface* getBridgeBehaviorInterface() = 0;
virtual BridgeTowerBehaviorInterface* getBridgeTowerBehaviorInterface() = 0;
virtual BridgeScaffoldBehaviorInterface* getBridgeScaffoldBehaviorInterface() = 0;
virtual OverchargeBehaviorInterface* getOverchargeBehaviorInterface() = 0;
virtual TransportPassengerInterface* getTransportPassengerInterface() = 0;
virtual CaveInterface* getCaveInterface() = 0;
virtual LandMineInterface* getLandMineInterface() = 0;
virtual DieModuleInterface* getEjectPilotDieInterface() = 0;
// move from UpdateModuleInterface (srj)
virtual ProjectileUpdateInterface* getProjectileUpdateInterface() = 0;
virtual AIUpdateInterface* getAIUpdateInterface() = 0;
virtual ExitInterface* getUpdateExitInterface() = 0;
virtual DockUpdateInterface* getDockUpdateInterface() = 0;
virtual RailedTransportDockUpdateInterface *getRailedTransportDockUpdateInterface( void ) = 0;
virtual SlowDeathBehaviorInterface* getSlowDeathBehaviorInterface() = 0;
virtual SpecialPowerUpdateInterface* getSpecialPowerUpdateInterface() = 0;
virtual SlavedUpdateInterface* getSlavedUpdateInterface() = 0;
virtual ProductionUpdateInterface* getProductionUpdateInterface() = 0;
virtual HordeUpdateInterface* getHordeUpdateInterface() = 0;
virtual PowerPlantUpdateInterface* getPowerPlantUpdateInterface() = 0;
virtual SpawnBehaviorInterface* getSpawnBehaviorInterface() = 0;
virtual CountermeasuresBehaviorInterface* getCountermeasuresBehaviorInterface() = 0;
virtual const CountermeasuresBehaviorInterface* getCountermeasuresBehaviorInterface() const = 0;
};
//-------------------------------------------------------------------------------------------------
class BehaviorModule : public ObjectModule, public BehaviorModuleInterface
{
MEMORY_POOL_GLUE_ABC( BehaviorModule )
public:
BehaviorModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
static Int getInterfaceMask() { return 0; }
static ModuleType getModuleType() { return MODULETYPE_BEHAVIOR; }
virtual BodyModuleInterface* getBody() { return NULL; }
virtual CollideModuleInterface* getCollide() { return NULL; }
virtual ContainModuleInterface* getContain() { return NULL; }
virtual CreateModuleInterface* getCreate() { return NULL; }
virtual DamageModuleInterface* getDamage() { return NULL; }
virtual DestroyModuleInterface* getDestroy() { return NULL; }
virtual DieModuleInterface* getDie() { return NULL; }
virtual SpecialPowerModuleInterface* getSpecialPower() { return NULL; }
virtual UpdateModuleInterface* getUpdate() { return NULL; }
virtual UpgradeModuleInterface* getUpgrade() { return NULL; }
virtual StealthUpdate* getStealth() { return NULL; }
virtual SpyVisionUpdate* getSpyVisionUpdate() { return NULL; }
virtual ParkingPlaceBehaviorInterface* getParkingPlaceBehaviorInterface() { return NULL; }
virtual RebuildHoleBehaviorInterface* getRebuildHoleBehaviorInterface() { return NULL; }
virtual BridgeBehaviorInterface* getBridgeBehaviorInterface() { return NULL; }
virtual BridgeTowerBehaviorInterface* getBridgeTowerBehaviorInterface() { return NULL; }
virtual BridgeScaffoldBehaviorInterface* getBridgeScaffoldBehaviorInterface() { return NULL; }
virtual OverchargeBehaviorInterface* getOverchargeBehaviorInterface() { return NULL; }
virtual TransportPassengerInterface* getTransportPassengerInterface() { return NULL; }
virtual CaveInterface* getCaveInterface() { return NULL; }
virtual LandMineInterface* getLandMineInterface() { return NULL; }
virtual DieModuleInterface* getEjectPilotDieInterface() { return NULL; }
// interface acquisition (moved from UpdateModule)
virtual ProjectileUpdateInterface* getProjectileUpdateInterface() { return NULL; }
virtual AIUpdateInterface* getAIUpdateInterface() { return NULL; }
virtual ExitInterface* getUpdateExitInterface() { return NULL; }
virtual DockUpdateInterface* getDockUpdateInterface() { return NULL; }
virtual RailedTransportDockUpdateInterface *getRailedTransportDockUpdateInterface( void ) { return NULL; }
virtual SlowDeathBehaviorInterface* getSlowDeathBehaviorInterface() { return NULL; }
virtual SpecialPowerUpdateInterface* getSpecialPowerUpdateInterface() { return NULL; }
virtual SlavedUpdateInterface* getSlavedUpdateInterface() { return NULL; }
virtual ProductionUpdateInterface* getProductionUpdateInterface() { return NULL; }
virtual HordeUpdateInterface* getHordeUpdateInterface() { return NULL; }
virtual PowerPlantUpdateInterface* getPowerPlantUpdateInterface() { return NULL; }
virtual SpawnBehaviorInterface* getSpawnBehaviorInterface() { return NULL; }
virtual CountermeasuresBehaviorInterface* getCountermeasuresBehaviorInterface() { return NULL; }
virtual const CountermeasuresBehaviorInterface* getCountermeasuresBehaviorInterface() const { return NULL; }
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
};
inline BehaviorModule::BehaviorModule( Thing *thing, const ModuleData* moduleData ) : ObjectModule( thing, moduleData ) { }
inline BehaviorModule::~BehaviorModule() { }
enum RunwayReservationType
{
RESERVATION_TAKEOFF,
RESERVATION_LANDING,
};
//-------------------------------------------------------------------------------------------------
class ParkingPlaceBehaviorInterface
{
public:
struct PPInfo
{
Coord3D parkingSpace;
Real parkingOrientation;
Coord3D runwayPrep;
Coord3D runwayStart;
Coord3D runwayEnd;
Coord3D runwayExit;
Coord3D runwayLandingStart;
Coord3D runwayLandingEnd;
Coord3D runwayApproach;
Coord3D hangarInternal;
Real runwayTakeoffDist;
Real hangarInternalOrient;
};
virtual Bool shouldReserveDoorWhenQueued(const ThingTemplate* thing) const = 0;
virtual Bool hasAvailableSpaceFor(const ThingTemplate* thing) const = 0;
virtual Bool hasReservedSpace(ObjectID id) const = 0;
virtual Int getSpaceIndex( ObjectID id ) const = 0;
virtual Bool reserveSpace(ObjectID id, Real parkingOffset, PPInfo* info) = 0;
virtual void releaseSpace(ObjectID id) = 0;
virtual Bool reserveRunway(ObjectID id, Bool forLanding) = 0;
virtual void calcPPInfo( ObjectID id, PPInfo *info ) = 0;
virtual void releaseRunway(ObjectID id) = 0;
virtual Int getRunwayCount() const = 0;
virtual ObjectID getRunwayReservation( Int r, RunwayReservationType type = RESERVATION_TAKEOFF ) = 0;
virtual void transferRunwayReservationToNextInLineForTakeoff(ObjectID id) = 0;
virtual Real getApproachHeight() const = 0;
virtual Real getLandingDeckHeightOffset() const = 0;
virtual void setHealee(Object* healee, Bool add) = 0;
virtual void killAllParkedUnits() = 0;
virtual void defectAllParkedUnits(Team* newTeam, UnsignedInt detectionTime) = 0;
virtual Bool calcBestParkingAssignment( ObjectID id, Coord3D *pos, Int *oldIndex = NULL, Int *newIndex = NULL ) = 0;
virtual const std::vector<Coord3D>* getTaxiLocations( ObjectID id ) const = 0;
virtual const std::vector<Coord3D>* getCreationLocations( ObjectID id ) const = 0;
};
//-------------------------------------------------------------------------------------------------
class TransportPassengerInterface
{
public:
virtual Bool tryToEvacuate( Bool exposeStealthedUnits ) = 0; ///< Will try to kick everybody out with game checks, and will return whether anyone made it
};
//-------------------------------------------------------------------------------------------------
class CaveInterface
{
public:
virtual void tryToSetCaveIndex( Int newIndex ) = 0; ///< Called by script as an alternative to instancing separate objects. 'Try', because can fail.
virtual void setOriginalTeam( Team *oldTeam ) = 0; ///< This is a distributed Garrison in terms of capturing, so when one node triggers the change, he needs to tell everyone, so anyone can do the un-change.
};
//-------------------------------------------------------------------------------------------------
class LandMineInterface
{
public:
virtual void setScootParms(const Coord3D& start, const Coord3D& end) = 0;
virtual void disarm() = 0;
};
//-------------------------------------------------------------------------------------------------
#endif

View file

@ -0,0 +1,308 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BodyModule.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BODYMODULE_H_
#define __BODYMODULE_H_
#include "Common/Module.h"
#include "GameLogic/Damage.h"
#include "GameLogic/ArmorSet.h"
#include "GameLogic/Module/BehaviorModule.h"
//-------------------------------------------------------------------------------------------------
/** OBJECT BODY MODULE base class */
//-------------------------------------------------------------------------------------------------
class WeaponTemplate;
//-------------------------------------------------------------------------------------------------
/** Damage states for structures
*
* NOTE: the macros below for IS_CONDITION_WORSE and IS_CONDITION_BETTER depend on this
* enumeration being in sequential order
*/
//-------------------------------------------------------------------------------------------------
enum BodyDamageType
{
BODY_PRISTINE, ///< unit should appear in pristine condition
BODY_DAMAGED, ///< unit has been damaged
BODY_REALLYDAMAGED, ///< unit is extremely damaged / nearly destroyed
BODY_RUBBLE, ///< unit has been reduced to rubble/corpse/exploded-hulk, etc
BODYDAMAGETYPE_COUNT
};
#ifdef DEFINE_BODYDAMAGETYPE_NAMES
static const char* TheBodyDamageTypeNames[] =
{
"PRISTINE",
"DAMAGED",
"REALLYDAMAGED",
"RUBBLE",
NULL
};
#endif
enum MaxHealthChangeType
{
SAME_CURRENTHEALTH,
PRESERVE_RATIO,
ADD_CURRENT_HEALTH_TOO,
FULLY_HEAL,
};
#ifdef DEFINE_MAXHEALTHCHANGETYPE_NAMES
static const char* TheMaxHealthChangeTypeNames[] =
{
"SAME_CURRENTHEALTH",
"PRESERVE_RATIO",
"ADD_CURRENT_HEALTH_TOO",
};
#endif
//
// is condition A worse than condition B ... NOTE: this assumes the conditions
// in BodyDamageType are in sequential order
//
// is a worse than b
#define IS_CONDITION_WORSE( a, b ) ( a > b )
// is a better than b
#define IS_CONDITION_BETTER( a, b ) ( a < b )
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class BodyModuleData : public BehaviorModuleData
{
public:
BodyModuleData()
{
}
static void buildFieldParse(MultiIniFieldParse& p)
{
BehaviorModuleData::buildFieldParse(p);
}
};
//-------------------------------------------------------------------------------------------------
class BodyModuleInterface
{
public:
/**
Try to damage this Object. The module's Armor
will be taken into account, so the actual damage done may vary
considerably from what you requested. Also note that (if damage is done)
the DamageFX will be invoked to provide a/v fx as appropriate.
*/
virtual void attemptDamage( DamageInfo *damageInfo ) = 0;
/**
Instead of having negative damage count as healing, or allowing access to the private
changeHealth Method, we will use this parallel to attemptDamage to do healing without hack.
*/
virtual void attemptHealing( DamageInfo *healingInfo ) = 0;
/**
Estimate the (unclipped) damage that would be done to this object
by the given damage (taking bonuses, armor, etc into account),
but DO NOT alter the body in any way. (This is used by the AI system
to choose weapons.)
*/
virtual Real estimateDamage( DamageInfoInput& damageInfo ) const = 0;
virtual Real getHealth() const = 0; ///< get current health
virtual Real getMaxHealth() const = 0;
virtual Real getInitialHealth() const = 0;
virtual Real getPreviousHealth() const = 0;
virtual UnsignedInt getSubdualDamageHealRate() const = 0;
virtual Real getSubdualDamageHealAmount() const = 0;
virtual Bool hasAnySubdualDamage() const = 0;
virtual Real getCurrentSubdualDamageAmount() const = 0;
virtual BodyDamageType getDamageState() const = 0;
virtual void setDamageState( BodyDamageType newState ) = 0; ///< control damage state directly. Will adjust hitpoints.
virtual void setAflame( Bool setting ) = 0;///< This is a major change like a damage state.
virtual void onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback ) = 0; ///< I just achieved this level right this moment
virtual void setArmorSetFlag(ArmorSetType ast) = 0;
virtual void clearArmorSetFlag(ArmorSetType ast) = 0;
virtual Bool testArmorSetFlag(ArmorSetType ast) = 0;
virtual const DamageInfo *getLastDamageInfo() const = 0;
virtual UnsignedInt getLastDamageTimestamp() const = 0;
virtual UnsignedInt getLastHealingTimestamp() const = 0;
virtual ObjectID getClearableLastAttacker() const = 0;
virtual void clearLastAttacker() = 0;
virtual Bool getFrontCrushed() const = 0;
virtual Bool getBackCrushed() const = 0;
virtual void setInitialHealth(Int initialPercent) = 0;
virtual void setMaxHealth( Real maxHealth, MaxHealthChangeType healthChangeType = SAME_CURRENTHEALTH ) = 0;
virtual void setFrontCrushed(Bool v) = 0;
virtual void setBackCrushed(Bool v) = 0;
virtual void applyDamageScalar( Real scalar ) = 0;
virtual Real getDamageScalar() const = 0;
/**
Change the module's health by the given delta. Note that
the module's DamageFX and Armor are NOT taken into
account, so you should think about what you're bypassing when you
call this directly (especially when when decreasing health, since
you probably want "attemptDamage" or "attemptHealing")
*/
virtual void internalChangeHealth( Real delta ) = 0;
virtual void setIndestructible( Bool indestructible ) = 0;
virtual Bool isIndestructible( void ) const = 0;
virtual void evaluateVisualCondition() = 0;
virtual void updateBodyParticleSystems() = 0; // made public for topple and building collapse updates -ML
};
//-------------------------------------------------------------------------------------------------
class BodyModule : public BehaviorModule, public BodyModuleInterface
{
MEMORY_POOL_GLUE_ABC( BodyModule )
public:
BodyModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
static Int getInterfaceMask() { return MODULEINTERFACE_BODY; }
// BehaviorModule
virtual BodyModuleInterface* getBody() { return this; }
/**
Try to damage this Object. The module's Armor
will be taken into account, so the actual damage done may vary
considerably from what you requested. Also note that (if damage is done)
the DamageFX will be invoked to provide a/v fx as appropriate.
*/
virtual void attemptDamage( DamageInfo *damageInfo ) = 0;
/**
Instead of having negative damage count as healing, or allowing access to the private
changeHealth Method, we will use this parallel to attemptDamage to do healing without hack.
*/
virtual void attemptHealing( DamageInfo *healingInfo ) = 0;
/**
Estimate the (unclipped) damage that would be done to this object
by the given damage (taking bonuses, armor, etc into account),
but DO NOT alter the body in any way. (This is used by the AI system
to choose weapons.)
*/
virtual Real estimateDamage( DamageInfoInput& damageInfo ) const = 0;
virtual Real getHealth() const = 0; ///< get current health
virtual Real getMaxHealth() const {return 0.0f;} ///< return max health
virtual Real getPreviousHealth() const { return 0.0f; } ///< return previous health
virtual UnsignedInt getSubdualDamageHealRate() const {return 0;}
virtual Real getSubdualDamageHealAmount() const {return 0.0f;}
virtual Bool hasAnySubdualDamage() const{return FALSE;}
virtual Real getCurrentSubdualDamageAmount() const { return 0.0f; }
virtual Real getInitialHealth() const {return 0.0f;} // return initial health
virtual BodyDamageType getDamageState() const = 0;
virtual void setDamageState( BodyDamageType newState ) = 0; ///< control damage state directly. Will adjust hitpoints.
virtual void setAflame( Bool setting ) = 0;///< This is a major change like a damage state.
virtual void onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback = FALSE ) = 0; ///< I just achieved this level right this moment
virtual void setArmorSetFlag(ArmorSetType ast) = 0;
virtual void clearArmorSetFlag(ArmorSetType ast) = 0;
virtual Bool testArmorSetFlag(ArmorSetType ast) = 0;
virtual const DamageInfo *getLastDamageInfo() const { return NULL; } ///< return info on last damage dealt to this object
virtual UnsignedInt getLastDamageTimestamp() const { return 0; } ///< return frame of last damage dealt
virtual UnsignedInt getLastHealingTimestamp() const { return 0; } ///< return frame of last healing dealt
virtual ObjectID getClearableLastAttacker() const { return INVALID_ID; }
virtual void clearLastAttacker() { }
virtual Bool getFrontCrushed() const { return false; }
virtual Bool getBackCrushed() const { return false; }
virtual void setInitialHealth(Int initialPercent) { } ///< Sets the inital load health %.
virtual void setMaxHealth(Real maxHealth, MaxHealthChangeType healthChangeType = SAME_CURRENTHEALTH ) { } ///< Sets the max health.
virtual void setFrontCrushed(Bool v) { DEBUG_CRASH(("you should never call this for generic Bodys")); }
virtual void setBackCrushed(Bool v) { DEBUG_CRASH(("you should never call this for generic Bodys")); }
virtual void setIndestructible( Bool indestructible ) { }
virtual Bool isIndestructible( void ) const { return TRUE; }
//Allows outside systems to apply defensive bonuses or penalties (they all stack as a multiplier!)
virtual void applyDamageScalar( Real scalar ) { m_damageScalar *= scalar; }
virtual Real getDamageScalar() const { return m_damageScalar; }
/**
Change the module's health by the given delta. Note that
the module's DamageFX and Armor are NOT taken into
account, so you should think about what you're bypassing when you
call this directly (especially when when decreasing health, since
you probably want "attemptDamage" or "attemptHealing")
*/
virtual void internalChangeHealth( Real delta ) = 0;
virtual void evaluateVisualCondition() { }
virtual void updateBodyParticleSystems() { };// made public for topple anf building collapse updates -ML
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
Real m_damageScalar;
};
inline BodyModule::BodyModule( Thing *thing, const ModuleData* moduleData ) : BehaviorModule( thing, moduleData ), m_damageScalar(1.0f) { }
inline BodyModule::~BodyModule() { }
#endif

View file

@ -0,0 +1,70 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BoneFXDamage.h /////////////////////////////////////////////////////////////////////
// Author: Bryan Cleveland, April 2002
// Desc: Damage module for the boneFX update module
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BONEFXDAMAGE_H_
#define __BONEFXDAMAGE_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/DamageModule.h"
//#include "GameLogic/Module/BodyModule.h" -- Yikes... not necessary to include this! (KM)
enum BodyDamageType; //Ahhhh much better!
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
class BoneFXDamage : public DamageModule
{
MAKE_STANDARD_MODULE_MACRO( BoneFXDamage );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BoneFXDamage, "BoneFXDamage" )
public:
BoneFXDamage( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// damage module methods
virtual void onDamage( DamageInfo *damageInfo ) { }
virtual void onHealing( DamageInfo *damageInfo ) { }
virtual void onBodyDamageStateChange( const DamageInfo* damageInfo,
BodyDamageType oldState,
BodyDamageType newState );
protected:
virtual void onObjectCreated();
};
#endif // end __BONEFXDAMAGE_H_

View file

@ -0,0 +1,281 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BoneFXUpdate.h /////////////////////////////////////////////////////////////////////
// Author: Bryan Cleveland, April 2002
// Desc: Update module that will fire off FX lists at bone locations at random intervals
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BONEFXUPDATE_H_
#define __BONEFXUPDATE_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameClient/ParticleSys.h"
#include "GameLogic/Module/UpdateModule.h"
//#include "GameLogic/Module/DamageModule.h" -- Yikes... not necessary to include this! (KM)
class DamageInfo; //Ahhhh much better!
#include "GameLogic/Module/BodyModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class FXList;
class ObjectCreationList;
class ParticleSystemTemplate;
// we can have this many effects of each type per body state
// NOTE: If you change this you should update the dataFieldParse[] table in the FXDamageModuleData
// to allow for the new indices into the effect arrays
enum { BONE_FX_MAX_BONES = 8 };
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
struct BoneLocInfo
{
AsciiString boneName; // bone name to use for effect pos
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
struct BaseBoneListInfo
{
BoneLocInfo locInfo;
GameClientRandomVariable gameClientDelay;
GameLogicRandomVariable gameLogicDelay;
Bool onlyOnce;
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
struct BoneFXListInfo : public BaseBoneListInfo
{
const FXList *fx;
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
struct BoneOCLInfo : public BaseBoneListInfo
{
const ObjectCreationList *ocl;
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
struct BoneParticleSystemInfo : public BaseBoneListInfo
{
const ParticleSystemTemplate *particleSysTemplate;
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class BoneFXUpdateModuleData : public UpdateModuleData
{
public:
BoneFXUpdateModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "DamageFXTypes", INI::parseDamageTypeFlags, NULL, offsetof( BoneFXUpdateModuleData, m_damageFXTypes ) },
{ "DamageOCLTypes", INI::parseDamageTypeFlags, NULL, offsetof( BoneFXUpdateModuleData, m_damageOCLTypes ) },
{ "DamageParticleTypes", INI::parseDamageTypeFlags, NULL, offsetof( BoneFXUpdateModuleData, m_damageParticleTypes ) },
{ "PristineFXList1", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_PRISTINE ][ 0 ] ) },
{ "PristineFXList2", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_PRISTINE ][ 1 ] ) },
{ "PristineFXList3", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_PRISTINE ][ 2 ] ) },
{ "PristineFXList4", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_PRISTINE ][ 3 ] ) },
{ "PristineFXList5", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_PRISTINE ][ 4 ] ) },
{ "PristineFXList6", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_PRISTINE ][ 5 ] ) },
{ "PristineFXList7", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_PRISTINE ][ 6 ] ) },
{ "PristineFXList8", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_PRISTINE ][ 7 ] ) },
{ "DamagedFXList1", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_DAMAGED ][ 0 ] ) },
{ "DamagedFXList2", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_DAMAGED ][ 1 ] ) },
{ "DamagedFXList3", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_DAMAGED ][ 2 ] ) },
{ "DamagedFXList4", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_DAMAGED ][ 3 ] ) },
{ "DamagedFXList5", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_DAMAGED ][ 4 ] ) },
{ "DamagedFXList6", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_DAMAGED ][ 5 ] ) },
{ "DamagedFXList7", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_DAMAGED ][ 6 ] ) },
{ "DamagedFXList8", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_DAMAGED ][ 7 ] ) },
{ "ReallyDamagedFXList1", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_REALLYDAMAGED ][ 0 ] ) },
{ "ReallyDamagedFXList2", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_REALLYDAMAGED ][ 1 ] ) },
{ "ReallyDamagedFXList3", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_REALLYDAMAGED ][ 2 ] ) },
{ "ReallyDamagedFXList4", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_REALLYDAMAGED ][ 3 ] ) },
{ "ReallyDamagedFXList5", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_REALLYDAMAGED ][ 4 ] ) },
{ "ReallyDamagedFXList6", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_REALLYDAMAGED ][ 5 ] ) },
{ "ReallyDamagedFXList7", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_REALLYDAMAGED ][ 6 ] ) },
{ "ReallyDamagedFXList8", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_REALLYDAMAGED ][ 7 ] ) },
{ "RubbleFXList1", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_RUBBLE ][ 0 ] ) },
{ "RubbleFXList2", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_RUBBLE ][ 1 ] ) },
{ "RubbleFXList3", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_RUBBLE ][ 2 ] ) },
{ "RubbleFXList4", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_RUBBLE ][ 3 ] ) },
{ "RubbleFXList5", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_RUBBLE ][ 4 ] ) },
{ "RubbleFXList6", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_RUBBLE ][ 5 ] ) },
{ "RubbleFXList7", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_RUBBLE ][ 6 ] ) },
{ "RubbleFXList8", BoneFXUpdateModuleData::parseFXList, NULL, offsetof( BoneFXUpdateModuleData, m_fxList[ BODY_RUBBLE ][ 7 ] ) },
{ "PristineOCL1", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_PRISTINE ][ 0 ] ) },
{ "PristineOCL2", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_PRISTINE ][ 1 ] ) },
{ "PristineOCL3", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_PRISTINE ][ 2 ] ) },
{ "PristineOCL4", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_PRISTINE ][ 3 ] ) },
{ "PristineOCL5", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_PRISTINE ][ 4 ] ) },
{ "PristineOCL6", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_PRISTINE ][ 5 ] ) },
{ "PristineOCL7", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_PRISTINE ][ 6 ] ) },
{ "PristineOCL8", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_PRISTINE ][ 7 ] ) },
{ "DamagedOCL1", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_DAMAGED ][ 0 ] ) },
{ "DamagedOCL2", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_DAMAGED ][ 1 ] ) },
{ "DamagedOCL3", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_DAMAGED ][ 2 ] ) },
{ "DamagedOCL4", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_DAMAGED ][ 3 ] ) },
{ "DamagedOCL5", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_DAMAGED ][ 4 ] ) },
{ "DamagedOCL6", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_DAMAGED ][ 5 ] ) },
{ "DamagedOCL7", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_DAMAGED ][ 6 ] ) },
{ "DamagedOCL8", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_DAMAGED ][ 7 ] ) },
{ "ReallyDamagedOCL1", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_REALLYDAMAGED ][ 0 ] ) },
{ "ReallyDamagedOCL2", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_REALLYDAMAGED ][ 1 ] ) },
{ "ReallyDamagedOCL3", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_REALLYDAMAGED ][ 2 ] ) },
{ "ReallyDamagedOCL4", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_REALLYDAMAGED ][ 3 ] ) },
{ "ReallyDamagedOCL5", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_REALLYDAMAGED ][ 4 ] ) },
{ "ReallyDamagedOCL6", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_REALLYDAMAGED ][ 5 ] ) },
{ "ReallyDamagedOCL7", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_REALLYDAMAGED ][ 6 ] ) },
{ "ReallyDamagedOCL8", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_REALLYDAMAGED ][ 7 ] ) },
{ "RubbleOCL1", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_RUBBLE ][ 0 ] ) },
{ "RubbleOCL2", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_RUBBLE ][ 1 ] ) },
{ "RubbleOCL3", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_RUBBLE ][ 2 ] ) },
{ "RubbleOCL4", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_RUBBLE ][ 3 ] ) },
{ "RubbleOCL5", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_RUBBLE ][ 4 ] ) },
{ "RubbleOCL6", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_RUBBLE ][ 5 ] ) },
{ "RubbleOCL7", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_RUBBLE ][ 6 ] ) },
{ "RubbleOCL8", BoneFXUpdateModuleData::parseObjectCreationList, NULL, offsetof( BoneFXUpdateModuleData, m_OCL[ BODY_RUBBLE ][ 7 ] ) },
{ "PristineParticleSystem1", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_PRISTINE ][ 0 ] ) },
{ "PristineParticleSystem2", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_PRISTINE ][ 1 ] ) },
{ "PristineParticleSystem3", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_PRISTINE ][ 2 ] ) },
{ "PristineParticleSystem4", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_PRISTINE ][ 3 ] ) },
{ "PristineParticleSystem5", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_PRISTINE ][ 4 ] ) },
{ "PristineParticleSystem6", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_PRISTINE ][ 5 ] ) },
{ "PristineParticleSystem7", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_PRISTINE ][ 6 ] ) },
{ "PristineParticleSystem8", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_PRISTINE ][ 7 ] ) },
{ "DamagedParticleSystem1", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_DAMAGED ][ 0 ] ) },
{ "DamagedParticleSystem2", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_DAMAGED ][ 1 ] ) },
{ "DamagedParticleSystem3", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_DAMAGED ][ 2 ] ) },
{ "DamagedParticleSystem4", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_DAMAGED ][ 3 ] ) },
{ "DamagedParticleSystem5", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_DAMAGED ][ 4 ] ) },
{ "DamagedParticleSystem6", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_DAMAGED ][ 5 ] ) },
{ "DamagedParticleSystem7", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_DAMAGED ][ 6 ] ) },
{ "DamagedParticleSystem8", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_DAMAGED ][ 7 ] ) },
{ "ReallyDamagedParticleSystem1", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_REALLYDAMAGED ][ 0 ] ) },
{ "ReallyDamagedParticleSystem2", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_REALLYDAMAGED ][ 1 ] ) },
{ "ReallyDamagedParticleSystem3", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_REALLYDAMAGED ][ 2 ] ) },
{ "ReallyDamagedParticleSystem4", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_REALLYDAMAGED ][ 3 ] ) },
{ "ReallyDamagedParticleSystem5", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_REALLYDAMAGED ][ 4 ] ) },
{ "ReallyDamagedParticleSystem6", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_REALLYDAMAGED ][ 5 ] ) },
{ "ReallyDamagedParticleSystem7", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_REALLYDAMAGED ][ 6 ] ) },
{ "ReallyDamagedParticleSystem8", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_REALLYDAMAGED ][ 7 ] ) },
{ "RubbleParticleSystem1", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_RUBBLE ][ 0 ] ) },
{ "RubbleParticleSystem2", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_RUBBLE ][ 1 ] ) },
{ "RubbleParticleSystem3", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_RUBBLE ][ 2 ] ) },
{ "RubbleParticleSystem4", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_RUBBLE ][ 3 ] ) },
{ "RubbleParticleSystem5", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_RUBBLE ][ 4 ] ) },
{ "RubbleParticleSystem6", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_RUBBLE ][ 5 ] ) },
{ "RubbleParticleSystem7", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_RUBBLE ][ 6 ] ) },
{ "RubbleParticleSystem8", BoneFXUpdateModuleData::parseParticleSystem, NULL, offsetof( BoneFXUpdateModuleData, m_particleSystem[ BODY_RUBBLE ][ 7 ] ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
static void parseFXList( INI *ini, void *instance, void *store, const void *userData );
static void parseObjectCreationList( INI *ini, void *instance, void *store, const void *userData );
static void parseParticleSystem( INI *ini, void *instance, void *store, const void *userData );
DamageTypeFlags m_damageFXTypes; ///< flags used to play or not play the effects
BoneFXListInfo m_fxList[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
DamageTypeFlags m_damageOCLTypes; ///< flags used to play or not play the effects
BoneOCLInfo m_OCL[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
DamageTypeFlags m_damageParticleTypes; ///< flags used to play or not play the effects
BoneParticleSystemInfo m_particleSystem[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
};
//-------------------------------------------------------------------------------------------------
class BoneFXUpdate : public UpdateModule
{
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( BoneFXUpdate, BoneFXUpdateModuleData );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BoneFXUpdate, "BoneFXUpdate" )
public:
BoneFXUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
void changeBodyDamageState( BodyDamageType oldState, BodyDamageType newState);
void stopAllBoneFX();
virtual UpdateSleepTime update();
protected:
virtual void onObjectCreated();
virtual void resolveBoneLocations();
void doFXListAtBone(const FXList *fxList, const Coord3D *bonePosition);
void doOCLAtBone(const ObjectCreationList *ocl, const Coord3D *bonePosition);
void doParticleSystemAtBone(const ParticleSystemTemplate *particleSystemTemplate, const Coord3D *bonePosition);
void killRunningParticleSystems();
void computeNextClientFXTime(const BaseBoneListInfo *info, Int &nextFrame);
void computeNextLogicFXTime(const BaseBoneListInfo *info, Int &nextFrame);
void initTimes();
typedef std::vector<ParticleSystemID> ParticleSystemIDVec;
/// we keep a record of attached particle system so we can detach and kill them when we want to
ParticleSystemIDVec m_particleSystemIDs;
Int m_nextFXFrame[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
Int m_nextOCLFrame[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
Int m_nextParticleSystemFrame[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
Coord3D m_FXBonePositions[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
Coord3D m_OCLBonePositions[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
Coord3D m_PSBonePositions[ BODYDAMAGETYPE_COUNT ][ BONE_FX_MAX_BONES ];
BodyDamageType m_curBodyState;
Bool m_bonesResolved[BODYDAMAGETYPE_COUNT];
Bool m_active;
};
#endif // end __BONEFXUPDATE_H_

View file

@ -0,0 +1,201 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BridgeBehavior.h /////////////////////////////////////////////////////////////////////////
// Author: Colin Day, July 2002
// Desc: Behavior module for bridges
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BRIDGE_BEHAVIOR_H_
#define __BRIDGE_BEHAVIOR_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "Common/AudioEventRTS.h"
#include "GameClient/TerrainRoads.h"
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/DamageModule.h"
#include "GameLogic/Module/Diemodule.h"
#include "GameLogic/Module/UpdateModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
enum BridgeTowerType;
class FXList;
class ObjectCreationList;
class Bridge;
class BridgeInfo;
// TYPES //////////////////////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------------------------------
struct TimeAndLocationInfo
{
UnsignedInt delay; ///< how long to wait to execute this
AsciiString boneName; ///< which bone to execute at
};
// ------------------------------------------------------------------------------------------------
struct BridgeFXInfo
{
const FXList *fx;
TimeAndLocationInfo timeAndLocationInfo;
};
// ------------------------------------------------------------------------------------------------
struct BridgeOCLInfo
{
const ObjectCreationList *ocl;
TimeAndLocationInfo timeAndLocationInfo;
};
// ------------------------------------------------------------------------------------------------
typedef std::list< BridgeFXInfo > BridgeFXList;
typedef std::list< BridgeOCLInfo > BridgeOCLList;
typedef std::list< ObjectID > ObjectIDList;
typedef ObjectIDList::iterator ObjectIDListIterator;
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BridgeBehaviorInterface
{
public:
virtual void setTower( BridgeTowerType towerType, Object *tower ) = 0;
virtual ObjectID getTowerID( BridgeTowerType towerType ) = 0;
virtual void createScaffolding( void ) = 0;
virtual void removeScaffolding( void ) = 0;
virtual Bool isScaffoldInMotion( void ) = 0;
virtual Bool isScaffoldPresent( void ) = 0;
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BridgeBehaviorModuleData : public BehaviorModuleData
{
public:
BridgeBehaviorModuleData( void );
~BridgeBehaviorModuleData( void );
static void buildFieldParse( MultiIniFieldParse &p );
Real m_lateralScaffoldSpeed;
Real m_verticalScaffoldSpeed;
BridgeFXList m_fx; ///< list of FX lists to execute
BridgeOCLList m_ocl; ///< list of OCL to execute
static void parseFX( INI *ini, void *instance, void *store, const void* userData );
static void parseOCL( INI *ini, void *instance, void *store, const void* userData );
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BridgeBehavior : public UpdateModule,
public BridgeBehaviorInterface,
public DamageModuleInterface,
public DieModuleInterface
{
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( BridgeBehavior, BridgeBehaviorModuleData );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BridgeBehavior, "BridgeBehavior" )
public:
BridgeBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// module methods
static Int getInterfaceMask( void ) { return (MODULEINTERFACE_DAMAGE) |
(MODULEINTERFACE_DIE) |
(MODULEINTERFACE_UPDATE); }
virtual BridgeBehaviorInterface* getBridgeBehaviorInterface( void ) { return this; }
virtual void onDelete( void );
// Damage methods
virtual DamageModuleInterface* getDamage( void ) { return this; }
virtual void onDamage( DamageInfo *damageInfo );
virtual void onHealing( DamageInfo *damageInfo );
virtual void onBodyDamageStateChange( const DamageInfo* damageInfo,
BodyDamageType oldState,
BodyDamageType newState );
// Die methods
virtual DieModuleInterface* getDie( void ) { return this; }
virtual void onDie( const DamageInfo *damageInfo );
// Update methods
virtual UpdateModuleInterface *getUpdate( void ) { return this; }
virtual UpdateSleepTime update( void );
// our own methods
static BridgeBehaviorInterface *getBridgeBehaviorInterfaceFromObject( Object *obj );
virtual void setTower( BridgeTowerType towerType, Object *tower ); ///< connect tower to us
virtual ObjectID getTowerID( BridgeTowerType towerType ); ///< retrive one of our towers
virtual void createScaffolding( void ); ///< create scaffolding around bridge
virtual void removeScaffolding( void ); ///< remove scaffolding around bridge
virtual Bool isScaffoldInMotion( void ); ///< is scaffold in motion
virtual Bool isScaffoldPresent( void ) { return m_scaffoldPresent; }
protected:
void resolveFX( void );
void handleObjectsOnBridgeOnDie( void );
void doAreaEffects( TerrainRoadType *bridgeTemplate, Bridge *bridge,
const ObjectCreationList *ocl, const FXList *fx );
void setScaffoldData( Object *obj,
Real *angle,
Real *sunkenHeight,
const Coord3D *riseToPos,
const Coord3D *buildPos,
const Coord3D *bridgeCenter );
void getRandomSurfacePosition( TerrainRoadType *bridgeTemplate,
const BridgeInfo *bridgeInfo,
Coord3D *pos );
ObjectID m_towerID[ BRIDGE_MAX_TOWERS ]; ///< the towers that are a part of us
// got damaged fx stuff
const ObjectCreationList *m_damageToOCL[ BODYDAMAGETYPE_COUNT ][ MAX_BRIDGE_BODY_FX ];
const FXList *m_damageToFX[ BODYDAMAGETYPE_COUNT ][ MAX_BRIDGE_BODY_FX ];
AudioEventRTS m_damageToSound[ BODYDAMAGETYPE_COUNT ];
// got repaired fx stuff
const ObjectCreationList *m_repairToOCL[ BODYDAMAGETYPE_COUNT ][ MAX_BRIDGE_BODY_FX ];
const FXList *m_repairToFX[ BODYDAMAGETYPE_COUNT ][ MAX_BRIDGE_BODY_FX ];
AudioEventRTS m_repairToSound[ BODYDAMAGETYPE_COUNT ];
Bool m_fxResolved; ///< TRUE until we've loaded our fx pointers and sounds
Bool m_scaffoldPresent; ///< TRUE when we have repair scaffolding visible
ObjectIDList m_scaffoldObjectIDList; ///< list of scaffold object IDs
UnsignedInt m_deathFrame; ///< frame we died on
};
#endif // end __BRIDGE_DAMAGE_H_

View file

@ -0,0 +1,117 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BridgeScaffoldBehavior.h /////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2002
// Desc: Bridge scaffold
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BRIDGE_SCAFFOLD_BEHAVIOR_H_
#define __BRIDGE_SCAFFOLD_BEHAVIOR_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/UpdateModule.h"
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
enum ScaffoldTargetMotion
{
STM_STILL,
STM_RISE,
STM_BUILD_ACROSS,
STM_TEAR_DOWN_ACROSS,
STM_SINK,
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BridgeScaffoldBehaviorInterface
{
public:
virtual void setPositions( const Coord3D *createPos,
const Coord3D *riseToPos,
const Coord3D *buildPos ) = 0;
virtual void setMotion( ScaffoldTargetMotion targetMotion ) = 0;
virtual ScaffoldTargetMotion getCurrentMotion( void ) = 0;
virtual void reverseMotion( void ) = 0;
virtual void setLateralSpeed( Real lateralSpeed ) = 0;
virtual void setVerticalSpeed( Real verticalSpeed ) = 0;
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BridgeScaffoldBehavior : public UpdateModule,
public BridgeScaffoldBehaviorInterface
{
MAKE_STANDARD_MODULE_MACRO( BridgeScaffoldBehavior );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BridgeScaffoldBehavior, "BridgeScaffoldBehavior" )
public:
BridgeScaffoldBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// behavior module methods
virtual BridgeScaffoldBehaviorInterface* getBridgeScaffoldBehaviorInterface() { return this; }
// update methods
virtual UpdateSleepTime update( void );
// bridge scaffold interface methods
virtual void setPositions( const Coord3D *createPos,
const Coord3D *riseToPos,
const Coord3D *buildPos );
virtual void setMotion( ScaffoldTargetMotion targetMotion );
virtual ScaffoldTargetMotion getCurrentMotion( void ) { return m_targetMotion; }
virtual void reverseMotion( void );
virtual void setLateralSpeed( Real lateralSpeed ) { m_lateralSpeed = lateralSpeed; }
virtual void setVerticalSpeed( Real verticalSpeed ) { m_verticalSpeed = verticalSpeed; }
// public interface acquisition
static BridgeScaffoldBehaviorInterface *getBridgeScaffoldBehaviorInterfaceFromObject( Object *obj );
protected:
void doVerticalMotion( void ); ///< do rise/sink vertical motion
void doLateralmotion( void ); ///< do lateral motion
ScaffoldTargetMotion m_targetMotion; ///< which way our motion should be going (build up, still, tear down etc)
Coord3D m_createPos; ///< initial position of object creation (in ground)
Coord3D m_riseToPos; ///< position we "rise to" out of the ground
Coord3D m_buildPos; ///< position we move to and stop at on the bridge surface
Real m_lateralSpeed; ///< speed for lateral motions
Real m_verticalSpeed; ///< speed for vertical motions
Coord3D m_targetPos; ///< current target position for our motion type
};
#endif // end __BRIDGE_SCAFFOLD_BEHAVIOR_H_

View file

@ -0,0 +1,99 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BridgeTowerBehavior.h ////////////////////////////////////////////////////////////////////
// Author: Colin Day, July 2002
// Desc: Behavior module for the towers attached to bridges that can be targeted
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BRIDGE_TOWER_BEHAVIOR_H_
#define __BRIDGE_TOWER_BEHAVIOR_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/DamageModule.h"
#include "GameLogic/Module/Diemodule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BridgeTowerBehaviorInterface
{
public:
virtual void setBridge( Object *bridge ) = 0;
virtual ObjectID getBridgeID( void ) = 0;
virtual void setTowerType( BridgeTowerType type ) = 0;
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BridgeTowerBehavior : public BehaviorModule,
public BridgeTowerBehaviorInterface,
public DieModuleInterface,
public DamageModuleInterface
{
MAKE_STANDARD_MODULE_MACRO( BridgeTowerBehavior );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BridgeTowerBehavior, "BridgeTowerBehavior" )
public:
BridgeTowerBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
static Int getInterfaceMask() { return (MODULEINTERFACE_DAMAGE) | (MODULEINTERFACE_DIE); }
BridgeTowerBehaviorInterface* getBridgeTowerBehaviorInterface( void ) { return this; }
virtual void setBridge( Object *bridge );
virtual ObjectID getBridgeID( void );
virtual void setTowerType( BridgeTowerType type );
static BridgeTowerBehaviorInterface *getBridgeTowerBehaviorInterfaceFromObject( Object *obj );
// Damage methods
virtual DamageModuleInterface* getDamage() { return this; }
virtual void onDamage( DamageInfo *damageInfo );
virtual void onHealing( DamageInfo *damageInfo );
virtual void onBodyDamageStateChange( const DamageInfo* damageInfo,
BodyDamageType oldState,
BodyDamageType newState );
// Die methods
virtual DieModuleInterface* getDie() { return this; }
virtual void onDie( const DamageInfo *damageInfo );
protected:
ObjectID m_bridgeID; ///< the bridge we're a part of
BridgeTowerType m_type; ///< type of tower (positioning) we are
};
#endif // end __BRIDGE_TOWER_DAMAGE_H_

View file

@ -0,0 +1,107 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BunkerBusterBehavior.h ////////////////////////////////////////////////////////////////
// Author: Mark Lorenzen, June 2003
// Desc: Behavior module for Bunker Buster... it kills garrisoned objects
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BUNKERBUSTER_BEHAVIOR_H_
#define __BUNKERBUSTER_BEHAVIOR_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Module/DieModule.h"
#include "GameClient/FXList.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class FXList;
class UpgradeTemplate;
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BunkerBusterBehaviorModuleData : //public UpdateModuleData
public BehaviorModuleData
{
public:
BunkerBusterBehaviorModuleData( void );
static void buildFieldParse( MultiIniFieldParse &p );
AsciiString m_upgradeRequired;///< Upgrade required to kill garrisoned units
const FXList *m_detonationFX; ///< FXList to play upon detonation
const FXList *m_crashThroughBunkerFX; ///< FXList to play as the bomb goes smashing through the bunker
UnsignedInt m_crashThroughBunkerFXFrequency; ///< How often to play the above FX
Real m_seismicEffectRadius;
Real m_seismicEffectMagnitude;
WeaponTemplate *m_shockwaveWeaponTemplate; ///< a weapon that gets fired when the buster gets busted, intended to generate a shockwave effect only
WeaponTemplate *m_occupantDamageWeaponTemplate; ///< a weapon to provide a damegeInfo that gets applied to each occupant of container struck as they are getting kicked out
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class BunkerBusterBehavior : public UpdateModule,
public DieModuleInterface
{
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( BunkerBusterBehavior, BunkerBusterBehaviorModuleData );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( BunkerBusterBehavior, "BunkerBusterBehavior" )
public:
BunkerBusterBehavior( Thing *thing, const ModuleData *modData );
// virtual destructor prototype provided by MemoryPoolObject
// module methods
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | (MODULEINTERFACE_DIE); }
// update module methods
virtual UpdateSleepTime update( void );
virtual void onObjectCreated( void );
// die module methods
virtual DieModuleInterface *getDie( void ) { return this; }
virtual void onDie( const DamageInfo *damageInfo );
protected:
void bustTheBunker( void );
const UpgradeTemplate *m_upgradeRequired; ///< Upgrade required to use the upgraded pulse FX
ObjectID m_victimID;
};
#endif // end __BUNKERBUSTER_BEHAVIOR_H_

View file

@ -0,0 +1,131 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CashBountyPower.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// created: Aug 2002
//
// Filename: CashBountyPower.h
//
//
// purpose:
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CashBountyPower_H_
#define __CashBountyPower_H_
//-----------------------------------------------------------------------------
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "GameLogic/Module/SpecialPowerModule.h"
#include "Common/Science.h"
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
class Thing;
class Player;
//-----------------------------------------------------------------------------
// TYPE DEFINES ///////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// INLINING ///////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// EXTERNALS //////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class CashBountyPowerModuleData : public SpecialPowerModuleData
{
public:
#ifdef NOT_IN_USE
struct Upgrades
{
ScienceType m_science;
Real m_bounty;
Upgrades() : m_science(SCIENCE_INVALID), m_bounty(0)
{
}
};
std::vector<Upgrades> m_upgrades;
#endif
Real m_defaultBounty;
CashBountyPowerModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
/** The OCL upgrade module */
//-------------------------------------------------------------------------------------------------
class CashBountyPower : public SpecialPowerModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CashBountyPower, "CashBountyPower" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CashBountyPower, CashBountyPowerModuleData );
public:
CashBountyPower( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
virtual void onObjectCreated();
//virtual void onBuildComplete(); ///< This is called when you are a finished game object
virtual void onSpecialPowerCreation(); ///< This is called when you are a finished game object
virtual void doSpecialPower( UnsignedInt commandOptions ) { return; }
protected:
Real findBounty() const;
};
#endif // __CashBountyPower_H_

View file

@ -0,0 +1,90 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CashHackSpecialPower.h ///////////////////////////////////////////////////////////////
// Author: Colin Day, June 2002
// Desc: The Spy Satellite will reveal shrouded areas of the map that the player chooses
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CASHHACKSPECIALPOWER_H_
#define __CASHHACKSPECIALPOWER_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/SpecialPowerModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Object;
class SpecialPowerTemplate;
struct FieldParse;
enum ScienceType;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class CashHackSpecialPowerModuleData : public SpecialPowerModuleData
{
public:
struct Upgrades
{
ScienceType m_science;
Int m_amountToSteal;
Upgrades() : m_science(SCIENCE_INVALID), m_amountToSteal(0)
{
}
};
std::vector<Upgrades> m_upgrades;
Int m_defaultAmountToSteal; ///< the amount of money that we will steal
CashHackSpecialPowerModuleData( void );
static void buildFieldParse( MultiIniFieldParse& p );
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class CashHackSpecialPower : public SpecialPowerModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CashHackSpecialPower, "CashHackSpecialPower" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CashHackSpecialPower, CashHackSpecialPowerModuleData )
public:
CashHackSpecialPower( Thing *thing, const ModuleData *moduleData );
// virtual destructor provided by memory pool object
virtual void doSpecialPowerAtObject( Object *obj, UnsignedInt commandOptions );
virtual void doSpecialPowerAtLocation( const Coord3D *loc, Real angle, UnsignedInt commandOptions );
protected:
Int findAmountToSteal() const;
};
#endif // end __CASHHACKSPECIALPOWER_H_

View file

@ -0,0 +1,131 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CaveContain.h ////////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, July 2002
// Desc: A version of OpenContain that overrides where the passengers are stored: one of CaveManager's
// entries. Changing entry is a script or ini command. All queries about capacity and
// contents are also redirected.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CAVE_CONTAIN_H_
#define __CAVE_CONTAIN_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/CreateModule.h"
#include "GameLogic/Module/OpenContain.h"
struct Sound;
class Team;
//-------------------------------------------------------------------------------------------------
class CaveContainModuleData : public OpenContainModuleData
{
public:
Int m_caveIndexData;
CaveContainModuleData()
{
m_caveIndexData = 0;// By default, all Caves will be grouped together as number 0
}
static void buildFieldParse(MultiIniFieldParse& p)
{
OpenContainModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "CaveIndex", INI::parseInt, NULL, offsetof( CaveContainModuleData, m_caveIndexData ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
class CaveContain : public OpenContain, public CreateModuleInterface, public CaveInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CaveContain, "CaveContain" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CaveContain, CaveContainModuleData )
public:
CaveContain( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual CreateModuleInterface* getCreate() { return this; }
virtual CaveInterface* getCaveInterface() { return this; }
static Int getInterfaceMask() { return OpenContain::getInterfaceMask() | (MODULEINTERFACE_CREATE); }
virtual OpenContain *asOpenContain() { return this; } ///< treat as open container
virtual Bool isGarrisonable() const { return false; } ///< can this unit be Garrisoned? (ick)
virtual Bool isBustable() const { return TRUE; } ///< can this container get busted by a bunkerbuster
virtual Bool isHealContain() const { return false; } ///< true when container only contains units while healing (not a transport!)
virtual void onContaining( Object *obj, Bool wasSelected ); ///< object now contains 'obj'
virtual void onRemoving( Object *obj ); ///< object no longer contains 'obj'
virtual Bool isValidContainerFor(const Object* obj, Bool checkCapacity) const;
virtual void addToContainList( Object *obj ); ///< The part of AddToContain that inheritors can override (Can't do whole thing because of all the private stuff involved)
virtual void removeFromContain( Object *obj, Bool exposeStealthUnits = FALSE ); ///< remove 'obj' from contain list
virtual void removeAllContained( Bool exposeStealthUnits = FALSE ); ///< remove all objects on contain list
/**
return the player that *appears* to control this unit. if null, use getObject()->getControllingPlayer() instead.
*/
virtual void recalcApparentControllingPlayer( void );
// contain list access
virtual void iterateContained( ContainIterateFunc func, void *userData, Bool reverse );
virtual UnsignedInt getContainCount() const;
virtual Int getContainMax( void ) const;
virtual const ContainedItemsList* getContainedItemsList() const;
virtual Bool isKickOutOnCapture(){ return FALSE; }///< Caves and Tunnels don't kick out on capture.
// override the onDie we inherit from OpenContain
virtual void onDie( const DamageInfo *damageInfo ); ///< the die callback
virtual void onCreate( void );
virtual void onBuildComplete(); ///< This is called when you are a finished game object
virtual Bool shouldDoOnBuildComplete() const { return m_needToRunOnBuildComplete; }
// Unique to Cave Contain
virtual void tryToSetCaveIndex( Int newIndex ); ///< Called by script as an alternative to instancing separate objects. 'Try', because can fail.
virtual void setOriginalTeam( Team *oldTeam ); ///< This is a distributed Garrison in terms of capturing, so when one node triggers the change, he needs to tell everyone, so anyone can do the un-change.
protected:
void changeTeamOnAllConnectedCaves( Team *newTeam, Bool setOriginalTeams ); ///< When one gets captured, all connected ones get captured. DistributedGarrison.
Bool m_needToRunOnBuildComplete;
Int m_caveIndex;
Team *m_originalTeam; ///< our original team before we were garrisoned
};
#endif // end __CAVE_CONTAIN_H_

View file

@ -0,0 +1,93 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CheckpointUpdate.h /////////////////////////////////////////////////////////////////////////////
// Author: Matthew D. Campbell, April 2002
// Desc: Reacts when an enemy is within range
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef CHECKPOINT_UPDATE_H
#define CHECKPOINT_UPDATE_H
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
#include "Common/KindOf.h"
//-------------------------------------------------------------------------------------------------
/** Checkpoint update */
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class CheckpointUpdateModuleData : public UpdateModuleData
{
public:
UnsignedInt m_enemyScanDelayTime;
CheckpointUpdateModuleData()
{
m_enemyScanDelayTime = LOGICFRAMES_PER_SECOND;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "ScanDelayTime", INI::parseDurationUnsignedInt, NULL, offsetof( CheckpointUpdateModuleData, m_enemyScanDelayTime ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class CheckpointUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CheckpointUpdate, "CheckpointUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CheckpointUpdate, CheckpointUpdateModuleData )
public:
CheckpointUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update();
protected:
Bool m_enemyNear;
Bool m_allyNear;
Real m_maxMinorRadius;
UnsignedInt m_enemyScanDelay;
void checkForAlliesAndEnemies( void );
};
#endif // end CHECKPOINT_UPDATE_H

View file

@ -0,0 +1,145 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// ChinookAIUpdate.h //////////
// Author: Steven Johnson, June 2002
#pragma once
#ifndef _ChinookAIUpdate_H_
#define _ChinookAIUpdate_H_
#include "GameLogic/AIStateMachine.h"
#include "GameLogic/Module/SupplyTruckAIUpdate.h"
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class ChinookAIUpdateModuleData : public SupplyTruckAIUpdateModuleData
{
public:
AsciiString m_ropeName;
AsciiString m_rotorWashParticleSystem;
Real m_rappelSpeed;
Real m_ropeDropSpeed;
Real m_ropeWidth;
Real m_ropeFinalHeight;
Real m_ropeWobbleLen;
Real m_ropeWobbleAmp;
Real m_ropeWobbleRate;
RGBColor m_ropeColor;
UnsignedInt m_numRopes;
UnsignedInt m_perRopeDelayMin;
UnsignedInt m_perRopeDelayMax;
Real m_minDropHeight;
Bool m_waitForRopesToDrop;
Int m_upgradedSupplyBoost;
ChinookAIUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
enum ChinookFlightStatus // Stored in save file, don't renumber. jba.
{
CHINOOK_TAKING_OFF = 0,
CHINOOK_FLYING = 1,
CHINOOK_DOING_COMBAT_DROP = 2,
CHINOOK_LANDING = 3,
CHINOOK_LANDED = 4
};
//-------------------------------------------------------------------------------------------------
class ChinookAIUpdate : public SupplyTruckAIUpdate
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ChinookAIUpdate, "ChinookAIUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( ChinookAIUpdate, ChinookAIUpdateModuleData )
public:
ChinookAIUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update();
virtual void aiDoCommand(const AICommandParms* parms);
virtual Bool chooseLocomotorSet(LocomotorSetType wst);
// this is present solely for some transports to override, so that they can land before
// allowing people to exit...
virtual AIFreeToExitType getAiFreeToExit(const Object* exiter) const;
virtual Bool isAllowedToAdjustDestination() const;
virtual ObjectID getBuildingToNotPathAround() const;
// this is present for subclasses (eg, Chinook) to override, to
// prevent supply-ferry behavior in some cases (eg, when toting passengers)
virtual Bool isAvailableForSupplying() const;
virtual Bool isCurrentlyFerryingSupplies() const;
virtual Bool isIdle() const;
const ChinookAIUpdateModuleData* friend_getData() const { return getChinookAIUpdateModuleData(); }
void friend_setFlightStatus(ChinookFlightStatus a) { m_flightStatus = a; }
void recordOriginalPosition( const Coord3D &pos ) { m_originalPos.set( &pos ); }
const Coord3D* getOriginalPosition() const { return &m_originalPos; }
Int ChinookAIUpdate::getUpgradedSupplyBoost() const;
protected:
virtual AIStateMachine* makeStateMachine();
virtual void privateCombatDrop( Object *target, const Coord3D& pos, CommandSourceType cmdSource );
virtual void privateGetRepaired( Object *repairDepot, CommandSourceType cmdSource );///< get repaired at repair depot
virtual void privateAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource );///< Extension. Also tell occupants to attackObject
virtual void privateAttackPosition( const Coord3D *pos, Int maxShotsToFire, CommandSourceType cmdSource );///< Extension. Also tell occupants to attackPosition
virtual void privateForceAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource );///< Extension. Also tell occupants to forceAttackObject
virtual void privateIdle(CommandSourceType cmdSource);
void private___TellPortableStructureToAttackWithMe( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource );
private:
void setMyState( StateID cmd, Object* target, const Coord3D* pos, CommandSourceType cmdSource );
void setAirfieldForHealing(ObjectID id);
AICommandParmsStorage m_pendingCommand;
ChinookFlightStatus m_flightStatus;
ObjectID m_airfieldForHealing;
Coord3D m_originalPos;
Bool m_hasPendingCommand;
};
#endif

View file

@ -0,0 +1,79 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CleanupAreaPower.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Created: September 2002
//
// Author: Kris Morness
//
// Makes use of the cleanup hazard update by augmenting the cleanup range
// until there is nothing left to cleanup at which time it goes idle.
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CLEANUP_AREA_POWER_H_
#define __CLEANUP_AREA_POWER_H_
//-----------------------------------------------------------------------------
#include "GameLogic/Module/SpecialPowerModule.h"
//-------------------------------------------------------------------------------------------------
class CleanupAreaPowerModuleData : public SpecialPowerModuleData
{
public:
Real m_cleanupMoveRange;
CleanupAreaPowerModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
class CleanupAreaPower : public SpecialPowerModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CleanupAreaPower, "CleanupAreaPower" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CleanupAreaPower, CleanupAreaPowerModuleData );
public:
CleanupAreaPower( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
virtual void doSpecialPowerAtLocation( const Coord3D *loc, Real angle, UnsignedInt commandOptions );
};
#endif

View file

@ -0,0 +1,97 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CleanupHazardUpdate.cpp //////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, August 2002
// Desc: Update module to handle independent targeting of hazards to cleanup.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CLEANUP_HAZARD_UPDATE_H_
#define __CLEANUP_HAZARD_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/KindOf.h"
#include "GameLogic/Module/UpdateModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class ThingTemplate;
class WeaponTemplate;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class CleanupHazardUpdateModuleData : public ModuleData
{
public:
WeaponSlotType m_weaponSlot;
UnsignedInt m_scanFrames;
Real m_scanRange;
CleanupHazardUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
/** The default update module */
//-------------------------------------------------------------------------------------------------
class CleanupHazardUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CleanupHazardUpdate, "CleanupHazardUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CleanupHazardUpdate, CleanupHazardUpdateModuleData );
public:
CleanupHazardUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onObjectCreated();
virtual UpdateSleepTime update();
Object* scanClosestTarget();
void fireWhenReady();
void setCleanupAreaParameters( const Coord3D *pos, Real range ); //This allows the unit to cleanup an area until clean, then the AI goes idle.
protected:
ObjectID m_bestTargetID;
Bool m_inRange;
Int m_nextScanFrames;
Int m_nextShotAvailableInFrames;
const WeaponTemplate *m_weaponTemplate;
//Cleanup area (temporary values).
Coord3D m_pos;
Real m_moveRange;
};
#endif

View file

@ -0,0 +1,106 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CollideModule.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CollideModule_H_
#define __CollideModule_H_
#include "Common/Module.h"
#include "GameLogic/Module/BehaviorModule.h"
//-------------------------------------------------------------------------------------------------
/** OBJECT COLLIDE MODULE
- Called when two objects collide (or when object collides with ground)
- Note in the 'collide' method that 'other' can be NULL, this indicates a
collision with the ground
- Also note the 'collide' method is the response for the object that THIS module
belongs to, we do not need to worry about the collision moudle of 'other',
it will have its own collide action called separately */
//-------------------------------------------------------------------------------------------------
class CollideModuleInterface
{
public:
virtual void onCollide( Object *other, const Coord3D *loc, const Coord3D *normal ) = 0;
virtual Bool wouldLikeToCollideWith(const Object* other) const = 0;
virtual Bool isHijackedVehicleCrateCollide() const = 0;
virtual Bool isSabotageBuildingCrateCollide() const = 0;
virtual Bool isCarBombCrateCollide() const = 0;
virtual Bool isRailroad() const = 0;
virtual Bool isSalvageCrateCollide() const = 0;
};
//-------------------------------------------------------------------------------------------------
class CollideModuleData : public BehaviorModuleData
{
public:
static void buildFieldParse(MultiIniFieldParse& p)
{
BehaviorModuleData::buildFieldParse(p);
}
};
//-------------------------------------------------------------------------------------------------
class CollideModule : public BehaviorModule,
public CollideModuleInterface
{
MEMORY_POOL_GLUE_ABC( CollideModule )
MAKE_STANDARD_MODULE_MACRO_ABC( CollideModule )
MAKE_STANDARD_MODULE_DATA_MACRO_ABC(CollideModule, CollideModuleData)
public:
CollideModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
static Int getInterfaceMask() { return MODULEINTERFACE_COLLIDE; }
// BehaviorModule
virtual CollideModuleInterface* getCollide() { return this; }
virtual void onCollide( Object *other, const Coord3D *loc, const Coord3D *normal ) = 0;
/// this is used for things like pilots, to determine if they can "enter" something
virtual Bool wouldLikeToCollideWith(const Object* other) const { return false; }
virtual Bool isHijackedVehicleCrateCollide() const { return false; }
virtual Bool isSabotageBuildingCrateCollide() const { return false; }
virtual Bool isCarBombCrateCollide() const { return false; }
virtual Bool isRailroad() const { return false;}
virtual Bool isSalvageCrateCollide() const { return false; }
};
inline CollideModule::CollideModule( Thing *thing, const ModuleData* moduleData ) : BehaviorModule( thing, moduleData ) { }
inline CollideModule::~CollideModule() { }
//-------------------------------------------------------------------------------------------------
#endif

View file

@ -0,0 +1,92 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CommandButtonHuntUpdate.cpp //////////////////////////////////////////////////////////////////////////
// Author: John Ahlquist, Sept. 2002
// Desc: Update module to handle wounded idle infantry finding a heal unit or structure.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __COMMAND_BUTTON_HUNT_UPDATE_H_
#define __COMMAND_BUTTON_HUNT_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/KindOf.h"
#include "GameLogic/Module/UpdateModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class ThingTemplate;
class WeaponTemplate;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class CommandButtonHuntUpdateModuleData : public ModuleData
{
public:
UnsignedInt m_scanFrames;
Real m_scanRange;
CommandButtonHuntUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
/** The default update module */
//-------------------------------------------------------------------------------------------------
class CommandButtonHuntUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CommandButtonHuntUpdate, "CommandButtonHuntUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CommandButtonHuntUpdate, CommandButtonHuntUpdateModuleData );
public:
CommandButtonHuntUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onObjectCreated();
virtual UpdateSleepTime update();
void setCommandButton(const AsciiString& buttonName);
protected:
Object* scanClosestTarget(void);
UpdateSleepTime huntSpecialPower(AIUpdateInterface *ai);
UpdateSleepTime huntWeapon(AIUpdateInterface *ai);
UpdateSleepTime huntEnter( AIUpdateInterface *ai );
protected:
AsciiString m_commandButtonName;
const CommandButton *m_commandButton;
};
#endif

View file

@ -0,0 +1,74 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CommandSetUpgrade.h /////////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, September 2002
// Desc: UpgradeModule that sets a new override string for Command Set look ups
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _COMMAND_SET_UPGRADE_H
#define _COMMAND_SET_UPGRADE_H
#include "GameLogic/Module/UpgradeModule.h"
//-----------------------------------------------------------------------------
class CommandSetUpgradeModuleData : public UpgradeModuleData
{
public:
AsciiString m_newCommandSet;
AsciiString m_newCommandSetAlt;
AsciiString m_triggerAlt;
CommandSetUpgradeModuleData()
{
m_newCommandSet = AsciiString::TheEmptyString;
m_newCommandSetAlt = AsciiString::TheEmptyString;
m_triggerAlt = "none";
}
static void buildFieldParse(MultiIniFieldParse& p);
};
//-----------------------------------------------------------------------------
class CommandSetUpgrade : public UpgradeModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CommandSetUpgrade, "CommandSetUpgrade" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CommandSetUpgrade, CommandSetUpgradeModuleData );
public:
CommandSetUpgrade( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
protected:
virtual void upgradeImplementation( ); ///< Here's the actual work of Upgrading
virtual Bool isSubObjectsUpgrade() { return false; }
};
#endif // _COMMAND_SET_UPGRADE_H

View file

@ -0,0 +1,214 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ContainModule.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __ContainModule_H_
#define __ContainModule_H_
#include "Common/Module.h"
#include "GameLogic/WeaponBonusConditionFlags.h" // Can't forward a typedef. This should me made a BitFlags class.
#include "GameLogic/Damage.h"
//-------------------------------------------------------------------------------------------------
class OpenContain;
class Player;
class ExitInterface;
class Matrix3D;
class Weapon;
enum CommandSourceType;
//-------------------------------------------------------------------------------------------------
enum ObjectEnterExitType
{
WANTS_TO_ENTER,
WANTS_TO_EXIT,
WANTS_NEITHER
};
enum EvacDisposition
{
EVAC_INVALID = 0,
EVAC_TO_LEFT,
EVAC_TO_RIGHT,
EVAC_BURST_FROM_CENTER,
};
//-------------------------------------------------------------------------------------------------
typedef std::list<Object*> ContainedItemsList;
//-------------------------------------------------------------------------------------------------
typedef ModuleData ContainModuleData;
//-------------------------------------------------------------------------------------------------
typedef void (*ContainIterateFunc)( Object *obj, void *userData ); ///< callback type for contain iterate
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class ContainModuleInterface
{
public:
// we have a two basic container types that it is convenient to query and use
virtual OpenContain *asOpenContain() = 0;
// our object changed position... react as appropriate.
virtual void containReactToTransformChange() = 0;
// containment is the basis for many complex systems, it helps us to have a formal
// place where we can monitor the outside world if we need to
//===============================================================================================
// Containment ==================================================================================
//===============================================================================================
virtual Bool isGarrisonable() const = 0;
virtual Bool isBustable() const = 0;
virtual Bool isSpecialZeroSlotContainer() const = 0;
virtual Bool isHealContain() const = 0;
virtual Bool isTunnelContain() const = 0;
virtual Bool isRiderChangeContain() const = 0;
virtual Bool isImmuneToClearBuildingAttacks() const = 0;
virtual Bool isSpecialOverlordStyleContainer() const = 0;
virtual Bool isAnyRiderAttacking() const = 0;
///< if my object gets selected, then my visible passengers should, too
///< this gets called from
virtual void clientVisibleContainedFlashAsSelected() = 0;
/**
this is used for containers that must do something to allow people to enter or exit...
eg, land (for Chinook), open door (whatever)... it's called with wants=WANTS_TO_ENTER
when something is in the enter state, and wants=ENTS_NOTHING when the unit has
either entered, or given up...
*/
virtual void onObjectWantsToEnterOrExit(Object* obj, ObjectEnterExitType wants) = 0;
// returns true iff there are objects currently waiting to enter.
virtual Bool hasObjectsWantingToEnterOrExit() const = 0;
/**
return the player that *appears* to control this unit, given an observing player.
if null, use getObject()->getControllingPlayer() instead.
*/
virtual const Player* getApparentControllingPlayer(const Player* observingPlayer) const = 0;
virtual void recalcApparentControllingPlayer() = 0;
//
// you will want to override onContaining() and onRemoving() if you need to
// do special actions at those event times for your module
//
virtual void onContaining( Object *obj, Bool wasSelected ) = 0; ///< object now contains 'obj'
virtual void onRemoving( Object *obj ) = 0; ///< object no longer contains 'obj'
virtual void onCapture( Player *oldOwner, Player *newOwner ) = 0; // Very important to handle capture of container, don't want to differ in teams from passenger to us.
virtual void onSelling() = 0;///< Container is being sold. Most people respond by kicking everyone out, but not all.
virtual Int getContainMax() const = 0; ///< The max needs to be virtual, but only two inheritors care. -1 means "I don't care".
virtual ExitInterface* getContainExitInterface() = 0;
virtual void orderAllPassengersToExit( CommandSourceType, Bool instantly ) = 0; ///< All of the smarts of exiting are in the passenger's AIExit. removeAllFrommContain is a last ditch system call, this is the game Evacuate
virtual void orderAllPassengersToIdle( CommandSourceType ) = 0; ///< Just like it sounds
virtual void orderAllPassengersToHackInternet( CommandSourceType ) = 0; ///< Just like it sounds
virtual void markAllPassengersDetected() = 0; ///< Cool game stuff got added to the system calls since this layer didn't exist, so this regains that functionality
//
// interface for containing objects inside of objects. Objects that are
// contained remove their drawable representations entirely from the client
//
/**
can this container contain this kind of object?
and, if checkCapacity is TRUE, does this container have enough space left to hold the given unit?
*/
virtual Bool isValidContainerFor(const Object* obj, Bool checkCapacity) const = 0;
virtual void addToContain( Object *obj ) = 0; ///< add 'obj' to contain list
virtual void addToContainList( Object *obj ) = 0; ///< The part of AddToContain that inheritors can override (Can't do whole thing because of all the private stuff involved)
virtual void removeFromContain( Object *obj, Bool exposeStealthUnits = FALSE ) = 0; ///< remove 'obj' from contain list
virtual void removeAllContained( Bool exposeStealthUnits = FALSE ) = 0; ///< remove all objects on contain list
virtual void killAllContained( void ) = 0; ///< kill all objects on contain list
virtual void harmAndForceExitAllContained( DamageInfo *info ) = 0; // apply canned damage against those containes
virtual Bool isEnclosingContainerFor( const Object *obj ) const = 0; ///< Does this type of Contain Visibly enclose its contents?
virtual Bool isPassengerAllowedToFire( ObjectID id = INVALID_ID ) const = 0; ///< Hey, can I shoot out of this container?
virtual void setPassengerAllowedToFire( Bool permission = TRUE ) = 0; ///< Hey, can I shoot out of this container?
virtual void setOverrideDestination( const Coord3D * ) = 0; ///< Instead of falling peacefully towards a clear spot, I will now aim here
virtual Bool isDisplayedOnControlBar() const = 0;///< Does this container display its contents on the ControlBar?
virtual Int getExtraSlotsInUse( void ) = 0;
virtual Bool isKickOutOnCapture() = 0;///< Does this contain module kick people out when captured?
// list access
virtual void iterateContained( ContainIterateFunc func, void *userData, Bool reverse ) = 0; ///< iterate the contain list
virtual UnsignedInt getContainCount() const = 0; ///< contained count
virtual const ContainedItemsList* getContainedItemsList() const = 0;
virtual const Object *friend_getRider() const = 0; ///< Damn. The draw order dependency bug for riders means that our draw module needs to cheat to get around it.
virtual Real getContainedItemsMass() const = 0;
virtual UnsignedInt getStealthUnitsContained() const = 0;
virtual Bool calcBestGarrisonPosition( Coord3D *sourcePos, const Coord3D *targetPos ) = 0;
virtual Bool attemptBestFirePointPosition( Object *source, Weapon *weapon, Object *victim ) = 0;
virtual Bool attemptBestFirePointPosition( Object *source, Weapon *weapon, const Coord3D *targetPos ) = 0;
// Player Occupancy.
virtual PlayerMaskType getPlayerWhoEntered(void) const = 0;
virtual void processDamageToContained(Real percentDamage) = 0; ///< Do our % damage to units now.
virtual Object* getClosestRider ( const Coord3D *pos ) = 0;
virtual void enableLoadSounds( Bool enable ) = 0;
virtual void setEvacDisposition( EvacDisposition disp ) = 0;
virtual Bool isWeaponBonusPassedToPassengers() const = 0;
virtual WeaponBonusConditionFlags getWeaponBonusPassedToPassengers() const = 0;
// this exists really just so someone can override it to prevent pip showings...
virtual Bool getContainerPipsToShow(Int& numTotal, Int& numFull)
{
numTotal = getContainMax();
numFull = getContainCount() + getExtraSlotsInUse();
// srj sez: this makes the pips display in the same manner as the inventory control bar...
// numTotal = getContainMax() - getExtraSlotsInUse();
// numFull = getContainCount();
return true;
}
};
//-------------------------------------------------------------------------------------------------
#endif

View file

@ -0,0 +1,93 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ConvertToCarBombCrateCollide.h /////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, April 2002
// Desc: A crate (actually a terrorist - mobile crate) that converts a car into a carbomb, activating
// it's weapon and then activating it's AI.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef CONVERT_TO_CAR_BOMB_CRATE_COLLIDE_H_
#define CONVERT_TO_CAR_BOMB_CRATE_COLLIDE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/Module.h"
#include "GameLogic/Module/CrateCollide.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class FXList;
//-------------------------------------------------------------------------------------------------
class ConvertToCarBombCrateCollideModuleData : public CrateCollideModuleData
{
public:
UnsignedInt m_rangeOfEffect;
const FXList *m_fxList;
ConvertToCarBombCrateCollideModuleData()
{
m_rangeOfEffect = 0;
m_fxList = NULL;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
CrateCollideModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "FXList", INI::parseFXList, NULL, offsetof( ConvertToCarBombCrateCollideModuleData, m_fxList ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
class ConvertToCarBombCrateCollide : public CrateCollide
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ConvertToCarBombCrateCollide, "ConvertToCarBombCrateCollide" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( ConvertToCarBombCrateCollide, ConvertToCarBombCrateCollideModuleData );
public:
ConvertToCarBombCrateCollide( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
protected:
/// This allows specific vetoes to certain types of crates and their data
virtual Bool isValidToExecute( const Object *other ) const;
/// This is the game logic execution function that all real CrateCollides will implement
virtual Bool executeCrateBehavior( Object *other );
virtual Bool isRailroad() const { return FALSE;};
virtual Bool isCarBombCrateCollide() const { return TRUE; }
};
#endif

View file

@ -0,0 +1,87 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// FILE: ConvertToHijackedVehicleCrateCollide.h
// Author: Mark Lorenzen, July 2002
// Desc: A crate (actually a terrorist - mobile crate) that makes the target vehicle switch
// sides, and kills its driver
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef CONVERT_TO_HIJACKED_VEHICLE_CRATE_COLLIDE_H_
#define CONVERT_TO_HIJACKED_VEHICLE_CRATE_COLLIDE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/Module.h"
#include "GameLogic/Module/CrateCollide.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
//-------------------------------------------------------------------------------------------------
class ConvertToHijackedVehicleCrateCollideModuleData : public CrateCollideModuleData
{
public:
UnsignedInt m_rangeOfEffect;
ConvertToHijackedVehicleCrateCollideModuleData()
{
m_rangeOfEffect = 0;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
CrateCollideModuleData::buildFieldParse(p);
}
};
//-------------------------------------------------------------------------------------------------
class ConvertToHijackedVehicleCrateCollide : public CrateCollide
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ConvertToHijackedVehicleCrateCollide, "ConvertToHijackedVehicleCrateCollide" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( ConvertToHijackedVehicleCrateCollide, ConvertToHijackedVehicleCrateCollideModuleData );
public:
ConvertToHijackedVehicleCrateCollide( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
protected:
/// This allows specific vetoes to certain types of crates and their data
virtual Bool isValidToExecute( const Object *other ) const;
/// This is the game logic execution function that all real CrateCollides will implement
virtual Bool executeCrateBehavior( Object *other );
virtual Bool isHijackedVehicleCrateCollide() const { return TRUE; }
};
#endif

View file

@ -0,0 +1,119 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CostModifierUpgrade.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// created: Aug 2002
//
// Filename: CostModifierUpgrade.h
//
// author: Chris Huybregts
//
// purpose:
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __COST_MODIFIER_UPGRADE_H_
#define __COST_MODIFIER_UPGRADE_H_
//-----------------------------------------------------------------------------
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "GameLogic/Module/UpgradeModule.h"
#include "Common/KindOf.h"
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
class Thing;
class Player;
//-----------------------------------------------------------------------------
// TYPE DEFINES ///////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// INLINING ///////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// EXTERNALS //////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class CostModifierUpgradeModuleData : public UpgradeModuleData
{
public:
CostModifierUpgradeModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p);
Real m_percentage;
KindOfMaskType m_kindOf;
};
//-------------------------------------------------------------------------------------------------
/** The OCL upgrade module */
//-------------------------------------------------------------------------------------------------
class CostModifierUpgrade : public UpgradeModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CostModifierUpgrade, "CostModifierUpgrade" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CostModifierUpgrade, CostModifierUpgradeModuleData );
public:
CostModifierUpgrade( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
virtual void onDelete( void ); ///< we have some work to do when this module goes away
virtual void onCapture( Player *oldOwner, Player *newOwner );
protected:
virtual void upgradeImplementation( void ); ///< Here's the actual work of Upgrading
virtual Bool isSubObjectsUpgrade() { return false; }
};
#endif // __COST_MODIFIER_UPGRADE_H_

View file

@ -0,0 +1,197 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CountermeasuresBehavior.h /////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, April 2003
// Desc: Handles countermeasure firing when under missile threat, and responsible
// for diverting missiles to the flares.
//------------------------------------------
#pragma once
#ifndef __COUNTERMEASURES_BEHAVIOR_H
#define __COUNTERMEASURES_BEHAVIOR_H
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameClient/ParticleSys.h"
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/UpgradeModule.h"
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Module/DamageModule.h"
#include "Common/BitFlagsIO.h"
class ParticleSystem;
class ParticleSystemTemplate;
//-------------------------------------------------------------------------------------------------
class CountermeasuresBehaviorModuleData : public UpdateModuleData
{
public:
UpgradeMuxData m_upgradeMuxData;
AsciiString m_flareTemplateName;
AsciiString m_flareBoneBaseName;
Real m_evasionRate;
UnsignedInt m_volleySize;
Real m_volleyArcAngle;
Real m_volleyVelocityFactor;
UnsignedInt m_framesBetweenVolleys;
UnsignedInt m_numberOfVolleys;
UnsignedInt m_reloadFrames;
UnsignedInt m_missileDecoyFrames;
UnsignedInt m_countermeasureReactionFrames;
Bool m_mustReloadAtAirfield;
CountermeasuresBehaviorModuleData()
{
m_volleySize = 0;
m_volleyArcAngle = 0.0f;
m_framesBetweenVolleys = 0;
m_numberOfVolleys = 0;
m_reloadFrames = 0;
m_evasionRate = 0.0f;
m_mustReloadAtAirfield = FALSE;
m_missileDecoyFrames = 0;
m_volleyVelocityFactor = 1.0f;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
static const FieldParse dataFieldParse[] =
{
{ "FlareTemplateName", INI::parseAsciiString, NULL, offsetof( CountermeasuresBehaviorModuleData, m_flareTemplateName ) },
{ "FlareBoneBaseName", INI::parseAsciiString, NULL, offsetof( CountermeasuresBehaviorModuleData, m_flareBoneBaseName ) },
{ "VolleySize", INI::parseUnsignedInt, NULL, offsetof( CountermeasuresBehaviorModuleData, m_volleySize ) },
{ "VolleyArcAngle", INI::parseAngleReal, NULL, offsetof( CountermeasuresBehaviorModuleData, m_volleyArcAngle ) },
{ "VolleyVelocityFactor", INI::parseReal, NULL, offsetof( CountermeasuresBehaviorModuleData, m_volleyVelocityFactor ) },
{ "DelayBetweenVolleys", INI::parseDurationUnsignedInt, NULL, offsetof( CountermeasuresBehaviorModuleData, m_framesBetweenVolleys ) },
{ "NumberOfVolleys", INI::parseUnsignedInt, NULL, offsetof( CountermeasuresBehaviorModuleData, m_numberOfVolleys ) },
{ "ReloadTime", INI::parseDurationUnsignedInt, NULL, offsetof( CountermeasuresBehaviorModuleData, m_reloadFrames ) },
{ "EvasionRate", INI::parsePercentToReal, NULL, offsetof( CountermeasuresBehaviorModuleData, m_evasionRate ) },
{ "MustReloadAtAirfield", INI::parseBool, NULL, offsetof( CountermeasuresBehaviorModuleData, m_mustReloadAtAirfield ) },
{ "MissileDecoyDelay", INI::parseDurationUnsignedInt, NULL, offsetof( CountermeasuresBehaviorModuleData, m_missileDecoyFrames ) },
{ "ReactionLaunchLatency", INI::parseDurationUnsignedInt, NULL, offsetof( CountermeasuresBehaviorModuleData, m_countermeasureReactionFrames ) },
{ 0, 0, 0, 0 }
};
UpdateModuleData::buildFieldParse(p);
p.add(dataFieldParse);
p.add(UpgradeMuxData::getFieldParse(), offsetof( CountermeasuresBehaviorModuleData, m_upgradeMuxData ));
}
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class CountermeasuresBehaviorInterface
{
public:
virtual void reportMissileForCountermeasures( Object *missile ) = 0;
virtual ObjectID calculateCountermeasureToDivertTo( const Object& victim ) = 0;
virtual void reloadCountermeasures() = 0;
virtual Bool isActive() const = 0;
};
typedef std::vector<ObjectID> CountermeasuresVec;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class CountermeasuresBehavior : public UpdateModule, public UpgradeMux, public CountermeasuresBehaviorInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CountermeasuresBehavior, "CountermeasuresBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CountermeasuresBehavior, CountermeasuresBehaviorModuleData )
public:
CountermeasuresBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// module methods
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | MODULEINTERFACE_UPGRADE; }
// BehaviorModule
virtual UpgradeModuleInterface* getUpgrade() { return this; }
virtual CountermeasuresBehaviorInterface* getCountermeasuresBehaviorInterface() { return this; }
virtual const CountermeasuresBehaviorInterface* getCountermeasuresBehaviorInterface() const { return this; }
// UpdateModuleInterface
virtual UpdateSleepTime update();
virtual DisabledMaskType getDisabledTypesToProcess() const { return MAKE_DISABLED_MASK( DISABLED_HELD ); }
// CountermeasuresBehaviorInterface
virtual void reportMissileForCountermeasures( Object *missile );
virtual ObjectID calculateCountermeasureToDivertTo( const Object& victim );
virtual void reloadCountermeasures();
virtual Bool isActive() const;
protected:
virtual void upgradeImplementation()
{
setWakeFrame(getObject(), UPDATE_SLEEP_NONE);
}
virtual void getUpgradeActivationMasks(UpgradeMaskType& activation, UpgradeMaskType& conflicting) const
{
getCountermeasuresBehaviorModuleData()->m_upgradeMuxData.getUpgradeActivationMasks(activation, conflicting);
}
virtual void performUpgradeFX()
{
getCountermeasuresBehaviorModuleData()->m_upgradeMuxData.performUpgradeFX(getObject());
}
virtual void processUpgradeRemoval()
{
// I can't take it any more. Let the record show that I think the UpgradeMux multiple inheritence is CRAP.
getCountermeasuresBehaviorModuleData()->m_upgradeMuxData.muxDataProcessUpgradeRemoval(getObject());
}
virtual Bool requiresAllActivationUpgrades() const
{
return getCountermeasuresBehaviorModuleData()->m_upgradeMuxData.m_requiresAllTriggers;
}
inline Bool isUpgradeActive() const { return isAlreadyUpgraded(); }
virtual Bool isSubObjectsUpgrade() { return false; }
void launchVolley();
private:
CountermeasuresVec m_counterMeasures; //vector of countermeasures in the world.
UnsignedInt m_availableCountermeasures; //number of countermeasures that can be launched to divert missiles.
UnsignedInt m_activeCountermeasures; //number of countermeasures currently able to divert missiles.
UnsignedInt m_divertedMissiles; //number of missiles that have been diverted to countermeasures.
UnsignedInt m_incomingMissiles; //grand total of all missiles that were ever fired at me.
UnsignedInt m_reactionFrame; //The frame countermeasures will be launched after initial hostile act.
UnsignedInt m_nextVolleyFrame; //Frame the next volley is fired.
UnsignedInt m_reloadFrame; //The frame countermeasures will be ready to use again.
};
#endif // __COUNTERMEASURES_BEHAVIOR_H

View file

@ -0,0 +1,113 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CrateCollide.h /////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, March 2002
// Desc: Abstract base Class Crate Collide
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef CRATE_COLLIDE_H_
#define CRATE_COLLIDE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/CollideModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class Anim2DTemplate;
class FXList;
enum ScienceType;
//-------------------------------------------------------------------------------------------------
class CrateCollideModuleData : public CollideModuleData
{
public:
KindOfMaskType m_kindof; ///< the kind(s) of units that can be collided with
KindOfMaskType m_kindofnot; ///< the kind(s) of units that CANNOT be collided with
Bool m_isForbidOwnerPlayer; ///< This crate cannot be picked up by the player of the dead thing that made it.
Bool m_isBuildingPickup; ///< This crate can be picked up by a Building (bypassing AI requirement)
Bool m_isHumanOnlyPickup; ///< Can this crate only be picked up by a human player? (Mission thing)
ScienceType m_pickupScience; ///< Can only be picked up by a unit whose player has this science
FXList *m_executeFX; ///< FXList to play when activated
AsciiString m_executionAnimationTemplate; ///< Anim2D to play at crate location
Real m_executeAnimationDisplayTimeInSeconds; ///< time to play animation for
Real m_executeAnimationZRisePerSecond; ///< rise animation up while playing
Bool m_executeAnimationFades; ///< animation fades out
CrateCollideModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
class CrateCollide : public CollideModule
{
MEMORY_POOL_GLUE_ABC( CrateCollide )
MAKE_STANDARD_MODULE_MACRO_ABC( CrateCollide )
MAKE_STANDARD_MODULE_DATA_MACRO_ABC( CrateCollide, CrateCollideModuleData )
public:
enum SabotageVictimType
{
SAB_VICTIM_GENERIC = 0,
SAB_VICTIM_COMMAND_CENTER,
SAB_VICTIM_FAKE_BUILDING,
SAB_VICTIM_INTERNET_CENTER,
SAB_VICTIM_MILITARY_FACTORY,
SAB_VICTIM_POWER_PLANT,
SAB_VICTIM_SUPERWEAPON,
SAB_VICTIM_SUPPLY_CENTER,
SAB_VICTIM_DROP_ZONE,
};
CrateCollide( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
/// This collide method gets called when collision occur
virtual void onCollide( Object *other, const Coord3D *loc, const Coord3D *normal );
virtual Bool wouldLikeToCollideWith(const Object* other) const { return isValidToExecute(other); }
virtual Bool isRailroad() const { return FALSE;};
virtual Bool isCarBombCrateCollide() const { return FALSE; }
virtual Bool isHijackedVehicleCrateCollide() const { return FALSE; }
virtual Bool isSabotageBuildingCrateCollide() const { return FALSE; }
void doSabotageFeedbackFX( const Object *other, SabotageVictimType type = SAB_VICTIM_GENERIC );
protected:
/// This is the game logic execution function that all real CrateCollides will implement
virtual Bool executeCrateBehavior( Object *other ) = 0;
/// This allows specific vetoes to certain types of crates and their data
virtual Bool isValidToExecute( const Object *other ) const;
};
#endif

View file

@ -0,0 +1,100 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CreateCrateDie.h /////////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, February 2002
// Desc: A chance to create a crate on death according to certain condition checks
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _CREATE_CRATE_DIE_H_
#define _CREATE_CRATE_DIE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/INI.h"
#include "GameLogic/Module/DieModule.h"
#include "Common/STLTypedefs.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class CrateTemplate;
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class CreateCrateDieModuleData : public DieModuleData
{
public:
AsciiStringList m_crateNameList;
CreateCrateDieModuleData()
{
// Added By Sadullah Nader
// Initializations missing and needed
m_crateNameList.clear();
}
~CreateCrateDieModuleData()
{
m_crateNameList.clear();
}
static void buildFieldParse(MultiIniFieldParse& p)
{
DieModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "CrateData", CreateCrateDieModuleData::parseCrateData, NULL, NULL },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
static void parseCrateData( INI* ini, void *instance, void * /*store*/, const void* /*userData*/ );
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class CreateCrateDie : public DieModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CreateCrateDie, "CreateCrateDie" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CreateCrateDie, CreateCrateDieModuleData )
public:
CreateCrateDie( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onDie( const DamageInfo *damageInfo );
private:
Bool testCreationChance( CrateTemplate const *currentCrateData );
Bool testVeterancyLevel( CrateTemplate const *currentCrateData );
Bool testKillerType( CrateTemplate const *currentCrateData, Object *killer );
Bool testKillerScience( CrateTemplate const *currentCrateData, Object *killer );
Object *createCrate( CrateTemplate const *currentCrateData );
};
#endif

View file

@ -0,0 +1,89 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CreateModule.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CreateModule_H_
#define __CreateModule_H_
#include "Common/Module.h"
#include "GameLogic/Module/BehaviorModule.h"
//-------------------------------------------------------------------------------------------------
/** OBJECT CREATE MODULE base class */
//-------------------------------------------------------------------------------------------------
class CreateModuleInterface
{
public:
virtual void onCreate() = 0; ///< This is called when you become a code Object
virtual void onBuildComplete() = 0; ///< This is called when you are a finished game object
virtual Bool shouldDoOnBuildComplete() const = 0;
};
//-------------------------------------------------------------------------------------------------
class CreateModuleData : public BehaviorModuleData
{
public:
static void buildFieldParse(MultiIniFieldParse& p)
{
BehaviorModuleData::buildFieldParse(p);
}
};
//-------------------------------------------------------------------------------------------------
class CreateModule : public BehaviorModule, public CreateModuleInterface
{
MEMORY_POOL_GLUE_ABC( CreateModule )
MAKE_STANDARD_MODULE_MACRO_ABC( CreateModule )
//MAKE_STANDARD_MODULE_DATA_MACRO_ABC(CreateModule, CreateModuleData)
public:
CreateModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
static Int getInterfaceMask() { return MODULEINTERFACE_CREATE; }
// BehaviorModule
virtual CreateModuleInterface* getCreate() { return this; }
virtual void onCreate() = 0; ///< This is called when you become a code Object
virtual void onBuildComplete(){ m_needToRunOnBuildComplete = FALSE; } ///< This is called when you are a finished game object
virtual Bool shouldDoOnBuildComplete() const { return m_needToRunOnBuildComplete; }
private:
Bool m_needToRunOnBuildComplete; ///< Prevent the multiple calling of onBuildComplete
};
#endif

View file

@ -0,0 +1,77 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CreateObjectDie.h /////////////////////////////////////////////////////////////////////////////
// Author: Michael S. Booth, January 2002
// Desc: Create object at current object's death
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _CREATE_OBJECT_DIE_H_
#define _CREATE_OBJECT_DIE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/INI.h"
#include "GameLogic/Module/DieModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class ObjectCreationList;
//-------------------------------------------------------------------------------------------------
class CreateObjectDieModuleData : public DieModuleData
{
public:
const ObjectCreationList* m_ocl; ///< object creaton list to make
Bool m_transferPreviousHealth; ///< Transfers previous health before death to the new object created.
CreateObjectDieModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
/** When this object dies, create another object in its place */
//-------------------------------------------------------------------------------------------------
class CreateObjectDie : public DieModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CreateObjectDie, "CreateObjectDie" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CreateObjectDie, CreateObjectDieModuleData );
public:
CreateObjectDie( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onDie( const DamageInfo *damageInfo );
};
#endif // _CREATE_OBJECT_DIE_H_

View file

@ -0,0 +1,106 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CrushDie.h /////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, November 2001
// Desc: Default die module
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CrushDie_H_
#define __CrushDie_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/AudioEventRTS.h"
#include "Common/INI.h"
#include "GameLogic/Module/DieModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
enum CrushEnum
{
TOTAL_CRUSH,
BACK_END_CRUSH,
FRONT_END_CRUSH,
NO_CRUSH,
CRUSH_COUNT
};
//-------------------------------------------------------------------------------------------------
class CrushDieModuleData : public DieModuleData
{
public:
AudioEventRTS m_crushSounds[CRUSH_COUNT];
Int m_crushSoundPercent[CRUSH_COUNT];
CrushDieModuleData()
{
for (int i = 0; i < CRUSH_COUNT; i++)
{
m_crushSoundPercent[i] = 100;
}
}
static void buildFieldParse(MultiIniFieldParse& p)
{
DieModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "TotalCrushSound", INI::parseAudioEventRTS, NULL, offsetof( CrushDieModuleData, m_crushSounds[TOTAL_CRUSH] ) },
{ "BackEndCrushSound", INI::parseAudioEventRTS, NULL, offsetof( CrushDieModuleData, m_crushSounds[BACK_END_CRUSH] ) },
{ "FrontEndCrushSound", INI::parseAudioEventRTS, NULL, offsetof( CrushDieModuleData, m_crushSounds[FRONT_END_CRUSH] ) },
{ "TotalCrushSoundPercent", INI::parseInt, NULL, offsetof( CrushDieModuleData, m_crushSoundPercent[TOTAL_CRUSH] ) },
{ "BackEndCrushSoundPercent", INI::parseInt, NULL, offsetof( CrushDieModuleData, m_crushSoundPercent[BACK_END_CRUSH] ) },
{ "FrontEndCrushSoundPercent",INI::parseInt, NULL, offsetof( CrushDieModuleData, m_crushSoundPercent[FRONT_END_CRUSH] ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
class CrushDie : public DieModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CrushDie, "CrushDie" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( CrushDie, CrushDieModuleData );
public:
CrushDie( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onDie( const DamageInfo *damageInfo );
};
#endif // __CrushDie_H_

View file

@ -0,0 +1,68 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DamDie.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, April 2002
// Desc: The big water dam dying
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DAMDIE_H_
#define __DAMDIE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/DieModule.h"
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class DamDieModuleData : public DieModuleData
{
public:
DamDieModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p);
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class DamDie : public DieModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DamDie, "DamDie" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DamDie, DamDieModuleData )
public:
DamDie( Thing *thing, const ModuleData* moduleData );
// virtual destructor prorotype provided by MemoryPoolObject
virtual void onDie( const DamageInfo *damageInfo );
};
#endif // end __DAMDIE_H_

View file

@ -0,0 +1,117 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DamageModule.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DamageModule_H_
#define __DamageModule_H_
#include "Common/Module.h"
#include "GameLogic/Damage.h"
#include "GameLogic/Module/BehaviorModule.h"
enum BodyDamageType;
//-------------------------------------------------------------------------------------------------
/** OBJECT DAMAGE MODULE base class */
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DamageModuleInterface
{
public:
virtual void onDamage( DamageInfo *damageInfo ) = 0; ///< damage callback
virtual void onHealing( DamageInfo *damageInfo ) = 0; ///< healing callback
virtual void onBodyDamageStateChange( const DamageInfo* damageInfo,
BodyDamageType oldState,
BodyDamageType newState) = 0; ///< state change callback
};
//-------------------------------------------------------------------------------------------------
class DamageModuleData : public BehaviorModuleData
{
public:
// DamageTypeFlags m_damageTypes;
DamageModuleData()
// : m_damageTypes(DAMAGE_TYPE_FLAGS_ALL)
{
}
static void buildFieldParse(MultiIniFieldParse& p)
{
BehaviorModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
// { "DamageTypes", INI::parseDamageTypeFlags, NULL, offsetof( DamageModuleData, m_damageTypes ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
class DamageModule : public BehaviorModule, public DamageModuleInterface
{
MEMORY_POOL_GLUE_ABC( DamageModule )
MAKE_STANDARD_MODULE_MACRO_ABC( DamageModule )
MAKE_STANDARD_MODULE_DATA_MACRO_ABC( DamageModule, DamageModuleData )
public:
DamageModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
// module methods
static Int getInterfaceMask() { return MODULEINTERFACE_DAMAGE; }
// BehaviorModule
virtual DamageModuleInterface* getDamage() { return this; }
// damage module callbacks
virtual void onDamage( DamageInfo *damageInfo ) = 0; ///< damage callback
virtual void onHealing( DamageInfo *damageInfo ) = 0; ///< healing callback
virtual void onBodyDamageStateChange( const DamageInfo* damageInfo,
BodyDamageType oldState,
BodyDamageType newState) = 0; ///< state change callback
protected:
};
inline DamageModule::DamageModule( Thing *thing, const ModuleData* moduleData ) : BehaviorModule( thing, moduleData ) { }
inline DamageModule::~DamageModule() { }
//-------------------------------------------------------------------------------------------------
#endif

View file

@ -0,0 +1,133 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DefaultProductionExitUpdate.h /////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, January, 2002
// Desc: Hand off produced Units to me so I can Exit them into the world with my specific style
// This instance simply spits the guy out at a point.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _DEFAULT_PRODUCTION_EXIT_UPDATE_H
#define _DEFAULT_PRODUCTION_EXIT_UPDATE_H
#include "GameLogic/Module/UpdateModule.h"
#include "Common/INI.h"
#include "Lib/BaseType.h"
class Object;
//-------------------------------------------------------------------------------------------------
class DefaultProductionExitUpdateModuleData : public UpdateModuleData
{
public:
Coord3D m_unitCreatePoint;
Coord3D m_naturalRallyPoint;
Bool m_useSpawnRallyPoint;
DefaultProductionExitUpdateModuleData()
{
m_unitCreatePoint.zero();
m_naturalRallyPoint.zero();
m_useSpawnRallyPoint = false;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "UnitCreatePoint", INI::parseCoord3D, NULL, offsetof( DefaultProductionExitUpdateModuleData, m_unitCreatePoint ) },
{ "NaturalRallyPoint", INI::parseCoord3D, NULL, offsetof( DefaultProductionExitUpdateModuleData, m_naturalRallyPoint ) },
{ "UseSpawnRallyPoint", INI::parseBool, NULL, offsetof( DefaultProductionExitUpdateModuleData, m_useSpawnRallyPoint ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
class DefaultProductionExitUpdate : public UpdateModule, public ExitInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DefaultProductionExitUpdate, "DefaultProductionExitUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DefaultProductionExitUpdate, DefaultProductionExitUpdateModuleData )
public:
virtual ExitInterface* getUpdateExitInterface() { return this; }
DefaultProductionExitUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// Required funcs to fufill interface requirements
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 ) { return DOOR_1; }
virtual void exitObjectViaDoor( Object *newObj, ExitDoorType exitDoor );
virtual void unreserveDoorForExit( ExitDoorType exitDoor ) { /* nothing */ }
virtual void exitObjectByBudding( Object *newObj, Object *budHost ) { return; }
virtual void setRallyPoint( const Coord3D *pos ); ///< define a "rally point" for units to move towards
virtual const Coord3D *getRallyPoint( void ) const; ///< define a "rally point" for units to move towards
virtual Bool useSpawnRallyPoint( void ) const;
virtual Bool getNaturalRallyPoint( Coord3D& rallyPoint, Bool offset = TRUE ) const; ///< get the natural "rally point" for units to move towards
virtual Bool getExitPosition( Coord3D& exitPosition ) const; ///< access to the "Door" position of the production object
virtual UpdateSleepTime update() { return UPDATE_SLEEP_FOREVER; }
protected:
Coord3D m_rallyPoint; ///< Where units should move to after they have reached the "natural" rally point
Bool m_rallyPointExists; ///< Only move to the rally point if this is true
};
//-------------------------------------------------------------------------------------------------
inline void DefaultProductionExitUpdate::setRallyPoint( const Coord3D *pos )
{
m_rallyPoint = *pos;
m_rallyPointExists = true;
}
//-------------------------------------------------------------------------------------------------
inline const Coord3D *DefaultProductionExitUpdate::getRallyPoint( void ) const
{
if (m_rallyPointExists)
return &m_rallyPoint;
return NULL;
}
//-------------------------------------------------------------------------------------------------
inline Bool DefaultProductionExitUpdate::useSpawnRallyPoint( void ) const
{
// Check if the building has requested spawn units (like those that are airdropped)
// to use the rally points of the building.
if (getDefaultProductionExitUpdateModuleData()->m_useSpawnRallyPoint)
return TRUE;
else
return FALSE;
}
#endif

View file

@ -0,0 +1,85 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// FILE: DefectorSpecialPower.h
// Author: Mark Lorenzen, JULY 2002
// Desc: General can click command cursor on any enemy, and it becomes his
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DEFECTORSPECIALPOWER_H_
#define __DEFECTORSPECIALPOWER_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/SpecialPowerModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Object;
class SpecialPowerTemplate;
struct FieldParse;
enum ScienceType;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DefectorSpecialPowerModuleData : public SpecialPowerModuleData
{
public:
DefectorSpecialPowerModuleData( void );
static void buildFieldParse( MultiIniFieldParse& p );
Real m_fatCursorRadius; ///< the distance around the target we will reveal
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DefectorSpecialPower : public SpecialPowerModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DefectorSpecialPower, "DefectorSpecialPower" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DefectorSpecialPower, DefectorSpecialPowerModuleData )
public:
DefectorSpecialPower( Thing *thing, const ModuleData *moduleData );
// virtual destructor prototype provided by memory pool object
virtual void doSpecialPowerAtObject( Object *obj, UnsignedInt commandOptions );
virtual void doSpecialPowerAtLocation( const Coord3D *loc, Real angle, UnsignedInt commandOptions );
protected:
};
#endif // end DefectorSpecialPower

View file

@ -0,0 +1,91 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DeletionUpdate.h /////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, August 2002
// Desc: Update that will count down a lifetime and destroy object when it reaches zero
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DELETION_UPDATE_H_
#define __DELETION_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
//-------------------------------------------------------------------------------------------------
class DeletionUpdateModuleData : public UpdateModuleData
{
public:
UnsignedInt m_minFrames;
UnsignedInt m_maxFrames;
DeletionUpdateModuleData()
{
m_minFrames = 0.0f;
m_maxFrames = 0.0f;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "MinLifetime", INI::parseDurationUnsignedInt, NULL, offsetof( DeletionUpdateModuleData, m_minFrames ) },
{ "MaxLifetime", INI::parseDurationUnsignedInt, NULL, offsetof( DeletionUpdateModuleData, m_maxFrames ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DeletionUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DeletionUpdate, "DeletionUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DeletionUpdate, DeletionUpdateModuleData )
public:
DeletionUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
void setLifetimeRange( UnsignedInt minFrames, UnsignedInt maxFrames );
UnsignedInt getDieFrame() { return m_dieFrame; }
virtual UpdateSleepTime update( void );
protected:
UnsignedInt calcSleepDelay(UnsignedInt minFrames, UnsignedInt maxFrames);
UnsignedInt m_dieFrame; ///< frame we die on
};
#endif

View file

@ -0,0 +1,388 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// DeliverPayloadAIUpdate.h ////////////
// Author: Graham Smallwood, March 2002
// Desc: State machine that controls the approach and deployment of airborne cargo
#pragma once
#ifndef _DELIVER_PAYLOAD_AI_UPDATE_H_
#define _DELIVER_PAYLOAD_AI_UPDATE_H_
#include "Common/StateMachine.h"
#include "GameLogic/Module/AIUpdate.h"
#include "GameClient/RadiusDecal.h"
class DeliverPayloadData;
//-------------------------------------------------------------------------------------------------
class DeliverPayloadStateMachine : public StateMachine
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DeliverPayloadStateMachine, "DeliverPayloadStateMachine" );
public:
DeliverPayloadStateMachine( Object *owner );
static Bool isOffMap( State *thisState, void* userData );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
};
//-------------------------------------------------------------------------------------------------
class ApproachState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ApproachState, "ApproachState")
//Approaching the drop zone
public:
ApproachState( StateMachine *machine ) :State( machine, "ApproachState" ) {}
virtual StateReturnType update();
virtual StateReturnType onEnter();
protected:
// snapshot interface STUBBED - no member vars to save. jba.
virtual void crc( Xfer *xfer ){};
virtual void xfer( Xfer *xfer ){XferVersion cv = 1; XferVersion v = cv; xfer->xferVersion( &v, cv );}
virtual void loadPostProcess(){};
};
EMPTY_DTOR(ApproachState)
//-------------------------------------------------------------------------------------------------
class DeliveringState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(DeliveringState, "DeliveringState")
// Kickin' stuff out the door
public:
DeliveringState( StateMachine *machine ) :State( machine, "DeliveringState" )
{
m_dropDelayLeft = 0;
m_didOpen = false;
}
virtual StateReturnType update();
virtual StateReturnType onEnter();
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
UnsignedInt m_dropDelayLeft;
Bool m_didOpen;
};
EMPTY_DTOR(DeliveringState)
//-------------------------------------------------------------------------------------------------
class ConsiderNewApproachState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ConsiderNewApproachState, "ConsiderNewApproachState")
//Should I try again? Has own data to keep track.
public:
ConsiderNewApproachState( StateMachine *machine ) : State( machine, "ConsiderNewApproachState" ), m_numberEntriesToState(0) { }
virtual StateReturnType update();
virtual StateReturnType onEnter();
virtual void onExit( StateExitType status );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
Int m_numberEntriesToState;
};
EMPTY_DTOR(ConsiderNewApproachState)
//-------------------------------------------------------------------------------------------------
class RecoverFromOffMapState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(RecoverFromOffMapState, "RecoverFromOffMapState")
public:
RecoverFromOffMapState( StateMachine *machine ) : State( machine, "RecoverFromOffMapState" ), m_reEntryFrame(0) { }
virtual StateReturnType update();
virtual StateReturnType onEnter();
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
private:
UnsignedInt m_reEntryFrame;
};
EMPTY_DTOR(RecoverFromOffMapState)
//-------------------------------------------------------------------------------------------------
class HeadOffMapState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(HeadOffMapState, "HeadOffMapState")
//I'm outta here
public:
HeadOffMapState( StateMachine *machine ) :State( machine, "HeadOffMapState" ) { facingDirectionUponDelivery.zero(); }
virtual StateReturnType update();
virtual StateReturnType onEnter();
protected:
// snapshot interface STUBBED - no member vars to save. jba.
virtual void crc( Xfer *xfer ){};
virtual void xfer( Xfer *xfer ){XferVersion cv = 1; XferVersion v = cv; xfer->xferVersion( &v, cv );}
virtual void loadPostProcess(){};
Coord3D facingDirectionUponDelivery;
};
EMPTY_DTOR(HeadOffMapState)
//-------------------------------------------------------------------------------------------------
class CleanUpState : public State
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(CleanUpState, "CleanUpState")
//Made it off map, delete ourselves
public:
CleanUpState( StateMachine *machine ) :State( machine, "CleanUpState" ) {}
virtual StateReturnType update(){return STATE_CONTINUE;}
virtual StateReturnType onEnter();
protected:
// snapshot interface STUBBED - no member vars to save. jba.
virtual void crc( Xfer *xfer ){};
virtual void xfer( Xfer *xfer ){XferVersion cv = 1; XferVersion v = cv; xfer->xferVersion( &v, cv );}
virtual void loadPostProcess(){};
};
EMPTY_DTOR(CleanUpState)
//-------------------------------------------------------------------------------------------------
enum
{
APPROACH, ///< Flying towards target
DELIVERING, ///< Delivering the payload to the target
CONSIDER_NEW_APPROACH, ///< Deciding if I should reapproach to deliver more payload or go home
RECOVER_FROM_OFF_MAP, ///< oops, went off the map, special recovery needed
HEAD_OFF_MAP, ///< We're all done here, take off into the sunset
CLEAN_UP, ///< Made it to the sunset. Delete peacefully, don't kill
};
//-------------------------------------------------------------------------------------------------
class DeliverPayloadAIUpdateModuleData : public AIUpdateModuleData
{
public:
UnsignedInt m_doorDelay;
Real m_maxDistanceToTarget; ///< How far away from target I can unload, plus how far after target I need to turn around at
Int m_maxNumberAttempts; ///< How many times I can re-approach
UnsignedInt m_dropDelay; ///< How long to wait after entering Deliver state (to allow for doors opening)
Coord3D m_dropOffset; ///< where to disgorge the guys, relative to me
Coord3D m_dropVariance; ///< variance in dropping position among guys that I am dropping
AsciiString m_putInContainerName;
RadiusDecalTemplate m_deliveryDecalTemplate;
Real m_deliveryDecalRadius;
DeliverPayloadAIUpdateModuleData()
{
m_doorDelay = 0;
m_maxDistanceToTarget = 0.0f;
m_maxNumberAttempts = 0;
m_dropDelay = 0;
m_dropOffset.zero();
m_dropVariance.zero();
m_deliveryDecalRadius = 0;
// Added By Sadullah Nader
// Initialization missing and needed
m_putInContainerName.clear();
// End Add
}
static void buildFieldParse(MultiIniFieldParse& p)
{
AIUpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
//These values represent script only reinforcements using deliverPayloadViaModuleData()!
//***********************************************************************************
//DO NOT ADD DATA HERE UNLESS YOU ARE SUPPORTING SCRIPTED TEAM REINFORCEMENT DELIVERY
//THESE DATA VALUES ARE SPECIFIED ONLY BY FACTIONUNIT.INI
//***********************************************************************************
{ "DoorDelay", INI::parseDurationUnsignedInt, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_doorDelay ) },
{ "PutInContainer", INI::parseAsciiString, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_putInContainerName ) },
{ "DeliveryDistance", INI::parseReal, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_maxDistanceToTarget ) },
{ "MaxAttempts", INI::parseInt, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_maxNumberAttempts ) },
{ "DropDelay", INI::parseDurationUnsignedInt, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_dropDelay ) },
{ "DropOffset", INI::parseCoord3D, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_dropOffset ) },
{ "DropVariance", INI::parseCoord3D, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_dropVariance ) },
{ "DeliveryDecal", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_deliveryDecalTemplate ) },
{ "DeliveryDecalRadius", INI::parseReal, NULL, offsetof( DeliverPayloadAIUpdateModuleData, m_deliveryDecalRadius ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//This data is set by DeliverPayloadNugget in ObjectCreationList. This struct contains
//all the necessary information for DeliverPayloadAIUpdate to perform it's necessary
//functions. If you add something here, make sure you add the parsing function inside
//DeliverPayloadNugget.
//***********************************************************************************
//THESE DATA VALUES ARE SPECIFIED ONLY BY OBJECTCREATIONLIST.INI
//***********************************************************************************
class DeliverPayloadData
{
public:
AsciiString m_visibleDropBoneName; ///< Where the payload is created (offset by current bone number 01-xx)
AsciiString m_visibleSubObjectName; ///< Visible subobject to show or hide (offset by current drop number 01-xx)
AsciiString m_visiblePayloadTemplateName;
Real m_distToTarget;
Real m_preOpenDistance;
Int m_maxAttempts;
Coord3D m_dropOffset;
Coord3D m_dropVariance;
UnsignedInt m_dropDelay;
Bool m_fireWeapon;
Bool m_selfDestructObject;
Int m_visibleNumBones; ///< The number of visible bones to process.
Real m_diveStartDistance;
Real m_diveEndDistance;
WeaponSlotType m_strafingWeaponSlot;
Int m_visibleItemsDroppedPerInterval;
Bool m_inheritTransportVelocity;
Bool m_isParachuteDirectly; ///< Instead of parachuting to below the point of exit, go ahead and bunch up on the target
Real m_exitPitchRate;
const FXList *m_strafeFX;
Real m_strafeLength;
const WeaponTemplate *m_visiblePayloadWeaponTemplate;
RadiusDecalTemplate m_deliveryDecalTemplate;
Real m_deliveryDecalRadius;
DeliverPayloadData()
{
m_distToTarget = 0.0f;
m_preOpenDistance = 0.0f;
m_maxAttempts = 1;
m_dropOffset.zero();
m_dropVariance.zero();
m_dropDelay = 0;
m_fireWeapon = false;
m_visibleNumBones = 0;
m_diveStartDistance = 0.0f;
m_diveEndDistance = 0.0f;
m_strafingWeaponSlot = (WeaponSlotType)-1;
m_visibleItemsDroppedPerInterval = 0;
m_inheritTransportVelocity = false;
m_isParachuteDirectly = FALSE;
m_exitPitchRate = 0.0f;
m_strafeFX = NULL;
m_strafeLength = 0.0f;
m_visiblePayloadWeaponTemplate = NULL;
m_selfDestructObject = FALSE;
m_deliveryDecalRadius = 0;
// Added By Sadullah Nader
// Initialization missing and needed
m_visibleDropBoneName.clear();
m_visiblePayloadTemplateName.clear();
m_visibleSubObjectName.clear();
// End Add
}
static const FieldParse* getFieldParse();
};
//-------------------------------------------------------------------------------------------------
class DeliverPayloadAIUpdate : public AIUpdateInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DeliverPayloadAIUpdate, "DeliverPayloadAIUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DeliverPayloadAIUpdate, DeliverPayloadAIUpdateModuleData )
private:
public:
DeliverPayloadAIUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual AIFreeToExitType getAiFreeToExit(const Object* exiter) const;
const Coord3D* getTargetPos() const { return &m_targetPos; }
const Coord3D* getMoveToPos() const { return &m_moveToPos; }
UnsignedInt getDoorDelay() const { return getDeliverPayloadAIUpdateModuleData()->m_doorDelay; }
Bool isDeliveringPayload() const { return m_deliverPayloadStateMachine != NULL; }
const ThingTemplate* getPutInContainerTemplateViaModuleData() const;
Real getAllowedDistanceToTarget() const { return m_data.m_distToTarget; }
Real getPreOpenDistance() const { return m_data.m_preOpenDistance; }
Int getMaxNumberAttempts() const { return m_data.m_maxAttempts; }
UnsignedInt getDropDelay() const { return m_data.m_dropDelay; }
const Coord3D& getDropOffset() const { return m_data.m_dropOffset; }
const Coord3D& getDropVariance() const { return m_data.m_dropVariance; }
Bool isFireWeapon() const { return m_data.m_fireWeapon; }
Int getVisibleItemsDelivered() const { return m_visibleItemsDelivered; }
void setVisibleItemsDelivered( Int num ) { m_visibleItemsDelivered = num; }
Bool isCloseEnoughToTarget();
Bool isOffMap() const;
Real calcMinTurnRadius(Real* timeToTravelThatDist) const;
void deliverPayload( const Coord3D *moveToPos, const Coord3D *targetPos, const DeliverPayloadData *data );
void deliverPayloadViaModuleData( const Coord3D *moveToPos );
const DeliverPayloadData* getData() { return &m_data; }
virtual UpdateSleepTime update();
void killDeliveryDecal();
void friend_setFreeToExit(Bool f) { m_freeToExit = f; }
void friend_setAcceptingCommands(Bool f) { m_acceptingCommands = f; }
protected:
virtual AIStateMachine* makeStateMachine();
virtual Bool isAllowedToRespondToAiCommands(const AICommandParms* parms) const;
DeliverPayloadStateMachine* m_deliverPayloadStateMachine; ///< Controls my special logic
Coord3D m_targetPos; ///< Where I plan to deliver my little friends, if obj is null
Coord3D m_moveToPos; ///< Where I am moving to.
DeliverPayloadData m_data;
Int m_visibleItemsDelivered;
RadiusDecal m_deliveryDecal;
Real m_previousDistanceSqr;
Bool m_freeToExit;
Bool m_acceptingCommands;
enum DiveState // Stored in save file as int, don't renumber! jba.
{
DIVESTATE_PREDIVE=0,
DIVESTATE_DIVING=1,
DIVESTATE_POSTDIVE=2,
};
DiveState m_diveState;
};
#endif

View file

@ -0,0 +1,92 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DemoTrapUpdate.cpp //////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, August 2002
// Desc: Update module to handle demo trap proximity triggering.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DEMO_TRAP_UPDATE_H_
#define __DEMO_TRAP_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/KindOf.h"
#include "GameLogic/Module/UpdateModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DemoTrapUpdateModuleData : public ModuleData
{
public:
WeaponTemplate *m_detonationWeaponTemplate;
KindOfMaskType m_ignoreKindOf;
WeaponSlotType m_manualModeWeaponSlot;
WeaponSlotType m_detonationWeaponSlot;
WeaponSlotType m_proximityModeWeaponSlot;
Real m_triggerDetonationRange;
UnsignedInt m_scanFrames;
Bool m_defaultsToProximityMode;
Bool m_friendlyDetonation;
Bool m_detonateWhenKilled;
DemoTrapUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
/** The default update module */
//-------------------------------------------------------------------------------------------------
class DemoTrapUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DemoTrapUpdate, "DemoTrapUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DemoTrapUpdate, DemoTrapUpdateModuleData );
public:
DemoTrapUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onObjectCreated();
virtual UpdateSleepTime update();
void detonate();
protected:
Int m_nextScanFrames;
Bool m_detonated;
};
#endif

View file

@ -0,0 +1,87 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DemoralizeSpecialPower.h /////////////////////////////////////////////////////////////////
// Author: Colin Day, July 2002
// Desc: Demoralize
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DEMORALIZE_SPECIAL_POWER_H_
#define __DEMORALIZE_SPECIAL_POWER_H_
#ifdef ALLOW_DEMORALIZE
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/SpecialPowerModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class FXList;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DemoralizeSpecialPowerModuleData : public SpecialPowerModuleData
{
public:
DemoralizeSpecialPowerModuleData( void );
static void buildFieldParse( MultiIniFieldParse& p );
Real m_baseRange; ///< base range for this special power
Real m_bonusRangePerCaptured; ///< additional range we get for each prisoner
Real m_maxRange; ///< no matter how many prisoners we have, this is max
UnsignedInt m_baseDurationInFrames; ///< duration of the demoralization (in frames)
UnsignedInt m_bonusDurationPerCapturedInFrames; ///< additional duration added for each prisoner we have
UnsignedInt m_maxDurationInFrames; ///< no matter how many prisoners we have, this is max
const FXList *m_fxList; ///< fx list to play
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DemoralizeSpecialPower : public SpecialPowerModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DemoralizeSpecialPower, "DemoralizeSpecialPower" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DemoralizeSpecialPower, DemoralizeSpecialPowerModuleData )
public:
DemoralizeSpecialPower( Thing *thing, const ModuleData *moduleData );
// virtual destructor prototype provided by memory pool object
virtual void doSpecialPowerAtObject( const Object *obj, UnsignedInt commandOptions );
virtual void doSpecialPowerAtLocation( const Coord3D *loc, Real angle, UnsignedInt commandOptions );
protected:
};
#endif // ALLOW_DEMORALIZE
#endif // end __DEMORALIZE_SPECIAL_POWER_H_

View file

@ -0,0 +1,121 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// DeployStyleAIUpdate.h ////////////
// Author: Kris Morness, August 2002
// Desc: State machine that allows deploying/undeploying to control the AI.
// When deployed, you can't move, when undeployed, you can't attack.
#pragma once
#ifndef __DEPLOY_STYLE_AI_UPDATE_H
#define __DEPLOY_STYLE_AI_UPDATE_H
#include "Common/StateMachine.h"
#include "GameLogic/Module/AIUpdate.h"
//-------------------------------------------------------------------------------------------------
enum DeployStateTypes
{
READY_TO_MOVE, ///< Mobile, can't attack.
DEPLOY, ///< Not mobile, can't attack, currently unpacking to attack
READY_TO_ATTACK, ///< Not mobile, can attack
UNDEPLOY, ///< Not mobile, can't attack, currently packing to move
ALIGNING_TURRETS, ///< While deployed, we must wait for the turret to go back to natural position prior to undeploying.
};
//-------------------------------------------------------------------------------------------------
class DeployStyleAIUpdateModuleData : public AIUpdateModuleData
{
public:
UnsignedInt m_unpackTime;
UnsignedInt m_packTime;
Bool m_resetTurretBeforePacking;
Bool m_turretsFunctionOnlyWhenDeployed;
Bool m_turretsMustCenterBeforePacking;
Bool m_manualDeployAnimations;
DeployStyleAIUpdateModuleData()
{
m_unpackTime = 0;
m_packTime = 0;
m_resetTurretBeforePacking = false;
m_turretsFunctionOnlyWhenDeployed = false;
// Added By Sadullah Nader
// Initialization necessary
m_turretsMustCenterBeforePacking = FALSE;
// End Add
m_manualDeployAnimations = FALSE;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
AIUpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "UnpackTime", INI::parseDurationUnsignedInt, NULL, offsetof( DeployStyleAIUpdateModuleData, m_unpackTime ) },
{ "PackTime", INI::parseDurationUnsignedInt, NULL, offsetof( DeployStyleAIUpdateModuleData, m_packTime ) },
{ "ResetTurretBeforePacking", INI::parseBool, NULL, offsetof( DeployStyleAIUpdateModuleData, m_resetTurretBeforePacking ) },
{ "TurretsFunctionOnlyWhenDeployed", INI::parseBool, NULL, offsetof( DeployStyleAIUpdateModuleData, m_turretsFunctionOnlyWhenDeployed ) },
{ "TurretsMustCenterBeforePacking", INI::parseBool, NULL, offsetof( DeployStyleAIUpdateModuleData, m_turretsMustCenterBeforePacking ) },
{ "ManualDeployAnimations", INI::parseBool, NULL, offsetof( DeployStyleAIUpdateModuleData, m_manualDeployAnimations ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
class DeployStyleAIUpdate : public AIUpdateInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DeployStyleAIUpdate, "DeployStyleAIUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DeployStyleAIUpdate, DeployStyleAIUpdateModuleData )
private:
public:
DeployStyleAIUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void aiDoCommand(const AICommandParms* parms);
virtual Bool isIdle() const;
virtual UpdateSleepTime update();
UnsignedInt getUnpackTime() const { return getDeployStyleAIUpdateModuleData()->m_unpackTime; }
UnsignedInt getPackTime() const { return getDeployStyleAIUpdateModuleData()->m_packTime; }
Bool doTurretsFunctionOnlyWhenDeployed() const { return getDeployStyleAIUpdateModuleData()->m_turretsFunctionOnlyWhenDeployed; }
Bool doTurretsHaveToCenterBeforePacking() const { return getDeployStyleAIUpdateModuleData()->m_turretsMustCenterBeforePacking; }
void setMyState( DeployStateTypes StateID, Bool reverseDeploy = FALSE );
protected:
DeployStateTypes m_state;
UnsignedInt m_frameToWaitForDeploy;
};
#endif

View file

@ -0,0 +1,58 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DestroyDie.h /////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, November 2001
// Desc: Default die module
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DestroyDie_H_
#define __DestroyDie_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/DieModule.h"
#include "Common/INI.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class DestroyDie : public DieModule
{
MAKE_STANDARD_MODULE_MACRO( DestroyDie );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DestroyDie, "DestroyDie" )
public:
DestroyDie( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual void onDie( const DamageInfo *damageInfo );
};
#endif // __DestroyDie_H_

View file

@ -0,0 +1,70 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DestroyModule.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DestroyModule_H_
#define __DestroyModule_H_
#include "Common/Module.h"
#include "GameLogic/Module/BehaviorModule.h"
//-------------------------------------------------------------------------------------------------
/** OBJECT DESTROY MODULE base class */
//-------------------------------------------------------------------------------------------------
class DestroyModuleInterface
{
public:
virtual void onDestroy() = 0;
};
//-------------------------------------------------------------------------------------------------
class DestroyModule : public BehaviorModule, public DestroyModuleInterface
{
MEMORY_POOL_GLUE_ABC( DestroyModule )
MAKE_STANDARD_MODULE_MACRO_ABC( DestroyModule )
public:
DestroyModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
static Int getInterfaceMask() { return MODULEINTERFACE_DESTROY; }
// BehaviorModule
virtual DestroyModuleInterface* getDestroy() { return this; }
virtual void onDestroy() = 0;
protected:
};
#endif

View file

@ -0,0 +1,112 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DieModule.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DieModule_H_
#define __DieModule_H_
#include "Common/Module.h"
#include "GameLogic/Damage.h"
#include "GameLogic/Module/BehaviorModule.h"
#include "Common/ObjectStatusTypes.h"
//-------------------------------------------------------------------------------------------------
/** OBJECT DIE MODULE base class */
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DieModuleInterface
{
public:
virtual void onDie( const DamageInfo *damageInfo ) = 0;
};
//-------------------------------------------------------------------------------------------------
class DieMuxData // does NOT inherit from ModuleData.
{
public:
DeathTypeFlags m_deathTypes;
VeterancyLevelFlags m_veterancyLevels;
ObjectStatusMaskType m_exemptStatus; ///< die module is ignored if any of these status bits are set
ObjectStatusMaskType m_requiredStatus; ///< die module is ignored if any of these status bits are clear
DieMuxData();
static const FieldParse* getFieldParse();
Bool isDieApplicable(const Object* obj, const DamageInfo *damageInfo) const;
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DieModuleData : public BehaviorModuleData
{
public:
DieMuxData m_dieMuxData;
static void buildFieldParse(MultiIniFieldParse& p)
{
BehaviorModuleData::buildFieldParse(p);
p.add(DieMuxData::getFieldParse(), offsetof( DieModuleData, m_dieMuxData ));
}
inline Bool isDieApplicable(const Object* obj, const DamageInfo *damageInfo) const { return m_dieMuxData.isDieApplicable(obj, damageInfo); }
};
//-------------------------------------------------------------------------------------------------
class DieModule : public BehaviorModule, public DieModuleInterface
{
MEMORY_POOL_GLUE_ABC( DieModule )
MAKE_STANDARD_MODULE_MACRO_ABC( DieModule )
MAKE_STANDARD_MODULE_DATA_MACRO_ABC(DieModule, DieModuleData)
public:
DieModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
static Int getInterfaceMask() { return MODULEINTERFACE_DIE; }
// BehaviorModule
virtual DieModuleInterface* getDie() { return this; }
void onDie( const DamageInfo *damageInfo ) = 0;
protected:
Bool isDieApplicable(const DamageInfo *damageInfo) const { return getDieModuleData()->isDieApplicable(getObject(), damageInfo); }
};
inline DieModule::DieModule( Thing *thing, const ModuleData* moduleData ) : BehaviorModule( thing, moduleData ) { }
inline DieModule::~DieModule() { }
#endif

View file

@ -0,0 +1,160 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DockUpdate.h /////////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood Feb 2002
// Desc: Behavior common to all DockUpdates is here. Everything but action()
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _DOCK_UPDATE_H_
#define _DOCK_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/INI.h"
#include "Common/GameMemory.h"
#include "Common/STLTypedefs.h"
#include "GameLogic/Module/UpdateModule.h"
enum
{
DEFAULT_APPROACH_VECTOR_SIZE = 10
};
enum
{
DYNAMIC_APPROACH_VECTOR_FLAG = -1
};
//-------------------------------------------------------------------------------------------------
class DockUpdateModuleData : public UpdateModuleData
{
public:
Int m_numberApproachPositionsData; // A positive number is an absolute, DYNAMIC_APPROACH_VECTOR_FLAG means dynamic vector
Bool m_isAllowPassthrough;
DockUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
class DockUpdate : public UpdateModule , public DockUpdateInterface
{
MEMORY_POOL_GLUE_ABC( DockUpdate )
MAKE_STANDARD_MODULE_MACRO_ABC( DockUpdate )
MAKE_STANDARD_MODULE_DATA_MACRO_ABC( DockUpdate, DockUpdateModuleData )
public:
DockUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor provided by memory pool object
/** Returns true if it is okay for the docker to approach and prepare to dock.
False could mean the queue is full, for example.
*/
virtual Bool isClearToApproach( Object const* docker ) const;
/** Give me a Queue point to drive to, and record that that point is taken.
Returning NULL means there are none free
*/
virtual Bool reserveApproachPosition( Object* docker, Coord3D *position, Int *index );
/** Give me the next Queue point to drive to, and record that that point is taken.
*/
virtual Bool advanceApproachPosition( Object* docker, Coord3D *position, Int *index );
/** Return true when it is OK for docker to begin entering the dock
The Dock will lift the restriction on one particular docker on its own,
so you must continually ask.
*/
virtual Bool isClearToEnter( Object const* docker ) const;
/** Return true when it is OK for docker to request a new Approach position. The dock is in
charge of keeping track of holes in the line, but the docker will remind us of their spot.
*/
virtual Bool isClearToAdvance( Object const* docker, Int dockerIndex ) const;
/** Give me the point that is the start of your docking path
Returning NULL means there is none free
All functions take docker as arg so we could have multiple docks on a building.
Docker is not assumed, it is recorded and checked.
*/
virtual void getEnterPosition( Object* docker, Coord3D *position );
/** Give me the middle point of the dock process where the action() happens */
virtual void getDockPosition( Object* docker, Coord3D *position );
/** Give me the point to drive to when I am done */
virtual void getExitPosition( Object* docker, Coord3D *position );
virtual void onApproachReached( Object* docker ); ///< I have reached the Approach Point.
virtual void onEnterReached( Object* docker ); ///< I have reached the Enter Point.
virtual void onDockReached( Object* docker ); ///< I have reached the Dock point
virtual void onExitReached( Object* docker ); ///< I have reached the exit. You are no longer busy
//The fact that action() is not here is intentional. This object cannot exist. You must
//derive off it and implement action().
virtual void cancelDock( Object* docker ); ///< Clear me from any reserved points, and if I was the reason you were Busy, you aren't anymore.
virtual Bool isDockOpen( void ) { return m_dockOpen; } ///< Is the dock open to accepting dockers
virtual void setDockOpen( Bool open ) { m_dockOpen = open; } ///< Open/Close the dock
virtual Bool isAllowPassthroughType(); ///< Not all docks allow you to path through them in your AIDock machine
virtual Bool isRallyPointAfterDockType(){return FALSE;} ///< A minority of docks want to give you a final command to their rally point
virtual void setDockCrippled( Bool setting ); ///< Game Logic can set me as inoperative. I get to decide what that means.
virtual UpdateSleepTime update(); ///< In charge of lifting dock restriction for one registered as Approached if all is ready
protected:
// These are const data read from the drawable when first asked for them
Coord3D m_enterPosition;
Coord3D m_dockPosition;
Coord3D m_exitPosition;
Int m_numberApproachPositions;
Int m_numberApproachPositionBones;
// These are real variables local to my specific needs here in DockUpdate
Bool m_positionsLoaded; ///< FALSE until we have loaded all the docking positions
VecCoord3D m_approachPositions;
ObjectIDVector m_approachPositionOwners; ///< Who is in or at least reserved each spot
BoolVector m_approachPositionReached; ///< Which positions have actually been reached
ObjectID m_activeDocker; ///< we could expand this to multiple dock paths since we always get docker in our methods
Bool m_dockerInside; ///< This is true while our active docker is between Enter and Exit. This is shorter than activeDocker's lifetime as it doesn't include approach to enter
Bool m_dockCrippled; ///< Has game logic set me as crippled?
Bool m_dockOpen; ///< Is the dock open for dockers
void loadDockPositions(); ///< load all the dock positions
Coord3D computeApproachPosition( Int positionIndex, Object *forWhom ); ///< Do a smart lookup of this bone position
};
#endif

View file

@ -0,0 +1,309 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DozerAIUpdate.h //////////////////////////////////////////////////////////////////////////
// Author: Colin Day, February 2002
// Desc: Dozer AI behavior
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DOZERAIUPDATE_H_
#define __DOZERAIUPDATE_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/AIUpdate.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class AudioEventRTS;
//-------------------------------------------------------------------------------------------------
/** The Dozer primary state machine */
//-------------------------------------------------------------------------------------------------
class DozerPrimaryStateMachine : public StateMachine
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DozerPrimaryStateMachine, "DozerPrimaryStateMachine" );
public:
DozerPrimaryStateMachine( Object *owner );
// virtual destructor prototypes provided by memory pool object
//-----------------------------------------------------------------------------------------------
// state transition conditions
static Bool isBuildMostImportant( State *thisState, void* userData );
static Bool isRepairMostImportant( State *thisState, void* userData );
static Bool isFortifyMostImportant( State *thisState, void* userData );
protected:
// snapshot interface
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
};
//-------------------------------------------------------------------------------------------------
/** Dozer behaviors that use action sub state machines */
//-------------------------------------------------------------------------------------------------
enum DozerTask // These enums are saved in the game save file, so DO NOT renumber them. jba.
{
DOZER_TASK_INVALID = -1,
DOZER_TASK_FIRST = 0,
DOZER_TASK_BUILD = DOZER_TASK_FIRST, ///< go build something
DOZER_TASK_REPAIR = 1, ///< go repair something
DOZER_TASK_FORTIFY = 2, ///< go fortify something
DOZER_NUM_TASKS // keep this last
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
enum DozerDockPoint // These enums are saved in the game save file, so DO NOT renumber them. jba.
{
DOZER_DOCK_POINT_START = 0,
DOZER_DOCK_POINT_ACTION = 1,
DOZER_DOCK_POINT_END = 2,
DOZER_NUM_DOCK_POINTS // keep this one last
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
enum DozerBuildSubTask // These enums are saved in the game save file, so DO NOT renumber them. jba.
{
DOZER_SELECT_BUILD_DOCK_LOCATION = 0,
DOZER_MOVING_TO_BUILD_DOCK_LOCATION = 1,
DOZER_DO_BUILD_AT_DOCK = 2
};
// ------------------------------------------------------------------------------------------------
/** This is no longer a leaf behavior. Someone else needs to combine this
* with another major AIUpdate. So provide an interface to satisfy the people
* who look this up by name. */
// ------------------------------------------------------------------------------------------------
class DozerAIInterface
{
// This is no longer a leaf behavior. Someone else needs to combine this
// with another major AIUpdate. So provide an interface to satisfy the people
// who look this up by name.
public:
virtual void onDelete( void ) = 0;
virtual Real getRepairHealthPerSecond( void ) const = 0; ///< get health to repair per second
virtual Real getBoredTime( void ) const = 0; ///< how long till we're bored
virtual Real getBoredRange( void ) const = 0; ///< when we're bored, we look this far away to do things
// methods to override for the dozer behaviors
virtual Object *construct( const ThingTemplate *what,
const Coord3D *pos, Real angle,
Player *owningPlayer,
Bool isRebuild ) = 0;
// get task information
virtual DozerTask getMostRecentCommand( void ) = 0; ///< return task that was most recently issued
virtual Bool isTaskPending( DozerTask task ) = 0; ///< is there a desire to do the requested task
virtual ObjectID getTaskTarget( DozerTask task ) = 0; ///< get target of task
virtual Bool isAnyTaskPending( void ) = 0; ///< is there any dozer task pending
virtual DozerTask getCurrentTask( void ) const = 0; ///< return the current task we're doing
// the following should only be used from inside the Dozer state machine!
// !!! *DO NOT CALL THIS AND SET THE TASK DIRECTLY TO AFFECT BEHAVIOR* !!! ///
virtual void setCurrentTask( DozerTask task ) = 0; ///< set the current task of the dozer
virtual Bool getIsRebuild( void ) = 0; ///< get whether or not this is a rebuild.
// task actions
virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requrested task
virtual void cancelTask( DozerTask task ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it
// internal methods to manage behavior from within the dozer state machine
virtual void internalTaskComplete( DozerTask task ) = 0; ///< set a dozer task as successfully completed
virtual void internalCancelTask( DozerTask task ) = 0; ///< cancel this task from the dozer
virtual void internalTaskCompleteOrCancelled( DozerTask task ) = 0; ///< this is called when tasks are cancelled or completed
/** return a dock point for the action and task (if valid) ... note it can return NULL
if no point has been set for the combination of task and point */
virtual const Coord3D* getDockPoint( DozerTask task, DozerDockPoint point ) = 0;
virtual void setBuildSubTask( DozerBuildSubTask subTask ) = 0;
virtual DozerBuildSubTask getBuildSubTask( void ) = 0;
// repairing
virtual Bool canAcceptNewRepair( Object *obj ) = 0;
virtual void createBridgeScaffolding( Object *bridgeTower ) = 0;
virtual void removeBridgeScaffolding( Object *bridgeTower ) = 0;
virtual void startBuildingSound( const AudioEventRTS *sound, ObjectID constructionSiteID ) = 0;
virtual void finishBuildingSound() = 0;
};
// ------------------------------------------------------------------------------------------------
/** NOTE: If you edit module data you must do it in both the Dozer *AND* the Worker */
// ------------------------------------------------------------------------------------------------
class DozerAIUpdateModuleData : public AIUpdateModuleData
{
public:
DozerAIUpdateModuleData( void );
// !!!
// !!! NOTE: If you edit module data you must do it in both the Dozer *AND* the Worker !!!
// !!!
Real m_repairHealthPercentPerSecond; ///< how many health points per second the dozer repairs at
Real m_boredTime; ///< after this many frames, a dozer will try to find something to do on its own
Real m_boredRange; ///< range the dozers try to auto repair when they're bored
static void buildFieldParse( MultiIniFieldParse &p );
};
//-------------------------------------------------------------------------------------------------
/** The Dozer AI Update interface. Dozers are workers that are capable of building all the
* structures available to a player, as well as repairing building, and fortifying
* civilian structures */
//-------------------------------------------------------------------------------------------------
class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DozerAIUpdate, "DozerAIUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DozerAIUpdate, DozerAIUpdateModuleData )
public:
static Bool findGoodBuildOrRepairPosition(const Object* me, const Object* target, Coord3D& positionOut);
static Object* findGoodBuildOrRepairPositionAndTarget(Object* me, Object* target, Coord3D& positionOut);
public:
DozerAIUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual DozerAIInterface* getDozerAIInterface() {return this;}
virtual const DozerAIInterface* getDozerAIInterface() const {return this;}
virtual void onDelete( void );
//
// module data methods ... this is LAME, multiple inheritance off an interface with replicated
// data and code, ick!
// NOTE: If you edit module data you must do it in both the Dozer *AND* the Worker
//
virtual Real getRepairHealthPerSecond( void ) const; ///< get health to repair per second
virtual Real getBoredTime( void ) const; ///< how long till we're bored
virtual Real getBoredRange( void ) const; ///< when we're bored, we look this far away to do things
// methods to override for the dozer behaviors
virtual Object* construct( const ThingTemplate *what,
const Coord3D *pos, Real angle,
Player *owningPlayer,
Bool isRebuild ); ///< construct an object
// get task information
virtual DozerTask getMostRecentCommand( void ); ///< return task that was most recently issued
virtual Bool isTaskPending( DozerTask task ); ///< is there a desire to do the requested task
virtual ObjectID getTaskTarget( DozerTask task ); ///< get target of task
virtual Bool isAnyTaskPending( void ); ///< is there any dozer task pending
virtual DozerTask getCurrentTask( void ) const { return m_currentTask; } ///< return the current task we're doing
virtual void setCurrentTask( DozerTask task ) { m_currentTask = task; } ///< set the current task of the dozer
virtual Bool getIsRebuild( void ) { return m_isRebuild; } ///< get whether or not this building is a rebuild.
// task actions
virtual void newTask( DozerTask task, Object *target ); ///< set a desire to do the requrested task
virtual void cancelTask( DozerTask task ); ///< cancel this task from the queue, if it's the current task the dozer will stop working on it
// internal methods to manage behavior from within the dozer state machine
virtual void internalTaskComplete( DozerTask task ); ///< set a dozer task as successfully completed
virtual void internalCancelTask( DozerTask task ); ///< cancel this task from the dozer
virtual void internalTaskCompleteOrCancelled( DozerTask task ); ///< this is called when tasks are cancelled or completed
/** return a dock point for the action and task (if valid) ... note it can return NULL
if no point has been set for the combination of task and point */
virtual const Coord3D* getDockPoint( DozerTask task, DozerDockPoint point );
virtual void setBuildSubTask( DozerBuildSubTask subTask ) { m_buildSubTask = subTask; };
virtual DozerBuildSubTask getBuildSubTask( void ) { return m_buildSubTask; }
virtual UpdateSleepTime update( void ); ///< the update entry point
// repairing
virtual Bool canAcceptNewRepair( Object *obj );
virtual void createBridgeScaffolding( Object *bridgeTower );
virtual void removeBridgeScaffolding( Object *bridgeTower );
virtual void startBuildingSound( const AudioEventRTS *sound, ObjectID constructionSiteID );
virtual void finishBuildingSound();
//
// the following methods must be overridden so that if a player issues a command the dozer
// can exit the internal state machine and do whatever the player says
//
virtual void aiDoCommand(const AICommandParms* parms);
protected:
virtual void privateRepair( Object *obj, CommandSourceType cmdSource ); ///< repair the target
virtual void privateResumeConstruction( Object *obj, CommandSourceType cmdSource ); ///< resume construction on obj
struct DozerTaskInfo
{
ObjectID m_targetObjectID; ///< target object ID of task
UnsignedInt m_taskOrderFrame; ///< logic frame we decided we wanted to do this task
} m_task[ DOZER_NUM_TASKS ]; ///< tasks we want to do indexed by DozerTask
DozerPrimaryStateMachine *m_dozerMachine; ///< the custom state machine for Dozer behavior
DozerTask m_currentTask; ///< current task the dozer is attending to (if any)
AudioEventRTS m_buildingSound; ///< sound is pulled from the object we are building!
Bool m_isRebuild; ///< is this a rebuild of a previous building?
//
// the following info array can be used if we want to have more complicated approaches
// to our target depending on our task
//
struct DozerDockPointInfo
{
Bool valid; ///< this point has been set and is valid
Coord3D location; ///< WORLD location
} m_dockPoint[ DOZER_NUM_TASKS ][ DOZER_NUM_DOCK_POINTS ];
DozerBuildSubTask m_buildSubTask; ///< for building and actually docking for the build
private:
void createMachines( void ); ///< create our behavior machines we need
};
#endif // __DOZERAIUPDATE_H_

View file

@ -0,0 +1,130 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DumbProjectileBehavior.h
// Author: Steven Johnson, July 2002
// Desc:
#pragma once
#ifndef _DumbProjectileBehavior_H_
#define _DumbProjectileBehavior_H_
#include "Common/GameType.h"
#include "Common/GlobalData.h"
#include "Common/STLTypeDefs.h"
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/CollideModule.h"
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/WeaponBonusConditionFlags.h"
#include "Common/INI.h"
#include "WWMath/Matrix3D.h"
class ParticleSystem;
class FXList;
//-------------------------------------------------------------------------------------------------
class DumbProjectileBehaviorModuleData : public UpdateModuleData
{
public:
/**
These four data define a Bezier curve. The first and last control points are the firer and victim.
*/
Real m_firstHeight; ///< The first airborne control point will be this high above the highest intervening terrain
Real m_secondHeight; ///< And the second, this.
Real m_firstPercentIndent; ///< The first point will be this percent along the target line
Real m_secondPercentIndent; ///< And the second, this.
UnsignedInt m_maxLifespan;
Bool m_tumbleRandomly;
Bool m_orientToFlightPath;
Bool m_detonateCallsKill;
Int m_garrisonHitKillCount;
KindOfMaskType m_garrisonHitKillKindof; ///< the kind(s) of units that can be collided with
KindOfMaskType m_garrisonHitKillKindofNot; ///< the kind(s) of units that CANNOT be collided with
const FXList* m_garrisonHitKillFX;
Real m_flightPathAdjustDistPerFrame;
DumbProjectileBehaviorModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
class DumbProjectileBehavior : public UpdateModule, public ProjectileUpdateInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DumbProjectileBehavior, "DumbProjectileBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DumbProjectileBehavior, DumbProjectileBehaviorModuleData );
public:
DumbProjectileBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor provided by memory pool object
// UpdateModuleInterface
virtual UpdateSleepTime update();
virtual ProjectileUpdateInterface* getProjectileUpdateInterface() { return this; }
// ProjectileUpdateInterface
virtual void projectileLaunchAtObjectOrPosition(const Object *victim, const Coord3D* victimPos, const Object *launcher, WeaponSlotType wslot, Int specificBarrelToUse, const WeaponTemplate* detWeap, const ParticleSystemTemplate* exhaustSysOverride);
virtual void projectileFireAtObjectOrPosition( const Object *victim, const Coord3D *victimPos, const WeaponTemplate *detWeap, const ParticleSystemTemplate* exhaustSysOverride );
virtual Bool projectileHandleCollision( Object *other );
virtual Bool projectileIsArmed() const { return true; }
virtual ObjectID projectileGetLauncherID() const { return m_launcherID; }
virtual void setFramesTillCountermeasureDiversionOccurs( UnsignedInt frames ) {}
virtual void projectileNowJammed() {}
protected:
void positionForLaunch(const Object *launcher, WeaponSlotType wslot, Int specificBarrelToUse);
void detonate();
private:
ObjectID m_launcherID; ///< ID of object that launched us (zero if not yet launched)
ObjectID m_victimID; ///< ID of object we are targeting (zero if not yet launched)
const WeaponTemplate* m_detonationWeaponTmpl; ///< weapon to fire at end (or null)
UnsignedInt m_lifespanFrame; ///< if we haven't collided by this frame, blow up anyway
VecCoord3D m_flightPath; ///< The frame by frame flight path in a Bezier curve
Coord3D m_flightPathStart; ///< where flight path started (in case we must regen it)
Coord3D m_flightPathEnd; ///< where flight path ends (in case we must regen it)
Real m_flightPathSpeed; ///< flight path speed (in case we must regen it)
Int m_flightPathSegments; ///< number of segments in the flightpath (in case we must regen it)
Int m_currentFlightPathStep; ///< Our current index in the flight path vector. Quicker than popping off.
WeaponBonusConditionFlags m_extraBonusFlags;
Bool m_hasDetonated; ///<
Bool calcFlightPath(Bool recalcNumSegments);
#if defined(_DEBUG) || defined(_INTERNAL)
void displayFlightPath(); ///< Uses little debug icons in worldspace to show the path chosen when it is decided upon
#endif
};
#endif // _DumbProjectileBehavior_H_

View file

@ -0,0 +1,108 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DynamicGeometryInfoUpdate.h //////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, April 2002
// Desc: Update module that changes the object's GeometryInfo
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DYNAMIC_GEOMETRY_INFO_UPDATE_H_
#define __DYNAMIC_GEOMETRY_INFO_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/Geometry.h"
#include "GameLogic/Module/UpdateModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class DynamicGeometryInfoUpdateModuleData : public ModuleData
{
public:
UnsignedInt m_initialDelay;
Real m_initialHeight;
Real m_initialMajorRadius;
Real m_initialMinorRadius;
Real m_finalHeight;
Real m_finalMajorRadius;
Real m_finalMinorRadius;
UnsignedInt m_transitionTime;
Bool m_reverseAtTransitionTime; ///< reverse directions once transition time is reached
// I will go from initial to final in transitionTime frames, smoothly.
// I won't change type until that is actually needed as a task.
DynamicGeometryInfoUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
/** The default update module */
//-------------------------------------------------------------------------------------------------
class DynamicGeometryInfoUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DynamicGeometryInfoUpdate, "DynamicGeometryInfoUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DynamicGeometryInfoUpdate, DynamicGeometryInfoUpdateModuleData );
public:
DynamicGeometryInfoUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update();
protected:
UnsignedInt m_startingDelayCountdown;
UnsignedInt m_timeActive;
Bool m_started;
Bool m_finished;
Bool m_reverseAtTransitionTime; ///< do a reverse at transition time
enum DynamicGeometryDirection { FORWARD = 1, BACKWARD = -1 };
DynamicGeometryDirection m_direction; ///< direction we're growing/shrinking
Bool m_switchedDirections; ///< TRUE once we've switched directions
Real m_initialHeight;
Real m_initialMajorRadius;
Real m_initialMinorRadius;
Real m_finalHeight;
Real m_finalMajorRadius;
Real m_finalMinorRadius;
};
#endif

View file

@ -0,0 +1,134 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DynamicShroudClearingRangeUpdate.h /////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, August 2002
// Desc: Changes the Objects shroud clearing range
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DYNAMIC_SHROUD_RANGE_UPDATE_H_
#define __DYNAMIC_SHROUD_RANGE_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
#include "GameClient/RadiusDecal.h"///< For the pseudo-wireframe decal effect
#define GRID_FX_DECAL_COUNT (30)
//-------------------------------------------------------------------------------------------------
class DynamicShroudClearingRangeUpdateModuleData : public UpdateModuleData
{
public:
UnsignedInt m_shrinkDelay; ///< wait until
UnsignedInt m_shrinkTime; ///< then shrink this fast
UnsignedInt m_growDelay; ///< wait until
UnsignedInt m_growTime; ///< then grow this fast
Real m_finalVision; ///< Then change to this
UnsignedInt m_changeInterval; ///< And update my Object every this long
UnsignedInt m_growInterval; ///< Update evey this long while growing
Bool m_doSpySatFX; ///< Do I do the pseudo-wireframe decal and blip effects?
RadiusDecalTemplate m_gridDecalTemplate;///< For the pseudo-wireframe decal effect
DynamicShroudClearingRangeUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DynamicShroudClearingRangeUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DynamicShroudClearingRangeUpdate, "DynamicShroudClearingRangeUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( DynamicShroudClearingRangeUpdate, DynamicShroudClearingRangeUpdateModuleData )
public:
DynamicShroudClearingRangeUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update();
void createGridDecals( const RadiusDecalTemplate& tmpl, Real radius, const Coord3D& pos );
void killGridDecals( void );
void animateGridDecals( void );
protected:
enum DSCRU_STATE
{
DSCRU_NOT_STARTED_YET,
DSCRU_GROWING,
DSCRU_SUSTAINING,
DSCRU_SHRINKING,
DSCRU_DONE_FOREVER,
DSCRU_SLEEPING
};
DSCRU_STATE m_state;
// Bool m_shrinkFinished; ///< Nothing left to do
// Bool m_shrinkStarted; ///< Working it
// UnsignedInt m_shrinkStartCountdown; ///< When I start to shrink
// UnsignedInt m_shrinkDeadline; ///< When I am done
//New Timer Parameters
Int m_stateCountDown;
Int m_totalFrames;
UnsignedInt m_growStartDeadline;
UnsignedInt m_sustainDeadline;
UnsignedInt m_shrinkStartDeadline;
UnsignedInt m_doneForeverFrame; ///< Just in case interval and state timing goes awry
///< This supercedes and makes us quit
UnsignedInt m_changeIntervalCountdown;///< How long till I change my vision range again
Bool m_decalsCreated; ///< Have I created the fx decals yet?
Real m_visionChangePerInterval; ///< How much I change each time.
Real m_nativeClearingRange; ///< What is my objects native vision range?
Real m_currentClearingRange; ///<ToKeepTrackOfWhere We are at
RadiusDecal m_gridDecal[GRID_FX_DECAL_COUNT];///< For the pseudo-wireframe decal effect
};
#endif

View file

@ -0,0 +1,242 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: EMPUpdate.h ///////////////////////////////////////////////////////////////////////
// Author: Mark Lorenzen Sept. 2002
// Desc: Update that makes the electromagnetic pulse field grow, fade and disable junk
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __EMPUPDATE_H_
#define __EMPUPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Module/DieModule.h"
#include "GameLogic/Weapon.h"
//-------------------------------------------------------------------------------------------------
class EMPUpdateModuleData : public UpdateModuleData
{
public:
UnsignedInt m_lifeFrames;
UnsignedInt m_startFadeFrame;
UnsignedInt m_disabledDuration;
Real m_startScale; ///< how big I start drawing
Real m_targetScaleMin; ///< how big I change to by the time I'm done
Real m_targetScaleMax; ///< how big I change to by the time I'm done
//Real m_spinRateMax; ///< how fast may I spin?
RGBColor m_startColor;
RGBColor m_endColor;
const ParticleSystemTemplate *m_disableFXParticleSystem;
Real m_sparksPerCubicFoot; //<just like it sounds
Real m_effectRadius;
Int m_rejectMask;
KindOfMaskType m_victimKindOf;
KindOfMaskType m_victimKindOfNot;
Bool m_doesNotAffectMyOwnBuildings;
EMPUpdateModuleData()
{
m_lifeFrames = 1;
m_startFadeFrame = 0;
m_startScale = 1.0f;
m_targetScaleMax = 1.0f;
m_targetScaleMin = 1.0f;
m_startColor.setFromInt(0xffffffff);
m_endColor.setFromInt (0x00000000);
//m_spinRateMax = 0.0f;
m_disabledDuration = 0;
m_disableFXParticleSystem = NULL;
m_sparksPerCubicFoot = 0.001f;
m_effectRadius = 200;
m_rejectMask = 0;
m_doesNotAffectMyOwnBuildings = FALSE;
m_victimKindOf.clear();
m_victimKindOfNot.clear();
}
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "Lifetime", INI::parseDurationUnsignedInt, NULL, offsetof( EMPUpdateModuleData, m_lifeFrames ) },
{ "StartFadeTime", INI::parseDurationUnsignedInt, NULL, offsetof( EMPUpdateModuleData, m_startFadeFrame ) },
{ "StartScale", INI::parseReal, NULL, offsetof( EMPUpdateModuleData, m_startScale ) },
{ "DisabledDuration", INI::parseDurationUnsignedInt, NULL, offsetof( EMPUpdateModuleData, m_disabledDuration ) },
//{ "SpinRateMax", INI::parseReal, NULL, offsetof( EMPUpdateModuleData, m_spinRateMax ) },
{ "TargetScaleMax", INI::parseReal, NULL, offsetof( EMPUpdateModuleData, m_targetScaleMax ) },
{ "TargetScaleMin", INI::parseReal, NULL, offsetof( EMPUpdateModuleData, m_targetScaleMin ) },
{ "StartColor", INI::parseRGBColor, NULL, offsetof( EMPUpdateModuleData, m_startColor ) },
{ "EndColor", INI::parseRGBColor, NULL, offsetof( EMPUpdateModuleData, m_endColor ) },
{ "DisableFXParticleSystem", INI::parseParticleSystemTemplate, NULL, offsetof( EMPUpdateModuleData, m_disableFXParticleSystem ) },
{ "SparksPerCubicFoot", INI::parseReal, NULL, offsetof( EMPUpdateModuleData, m_sparksPerCubicFoot ) },
{ "EffectRadius", INI::parseReal, NULL, offsetof( EMPUpdateModuleData, m_effectRadius ) },
{ "DoesNotAffect", INI::parseBitString32, TheWeaponAffectsMaskNames, offsetof(EMPUpdateModuleData, m_rejectMask) },
{ "DoesNotAffectMyOwnBuildings", INI::parseBool, NULL, offsetof( EMPUpdateModuleData, m_doesNotAffectMyOwnBuildings ) },
{ "VictimRequiredKindOf", KindOfMaskType::parseFromINI, NULL, offsetof( EMPUpdateModuleData, m_victimKindOf ) },
{ "VictimForbiddenKindOf", KindOfMaskType::parseFromINI, NULL, offsetof( EMPUpdateModuleData, m_victimKindOfNot ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class EMPUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( EMPUpdate, "EMPUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( EMPUpdate, EMPUpdateModuleData )
public:
EMPUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
UnsignedInt getDieFrame() { return m_dieFrame; }
virtual UpdateSleepTime update( void );
void doDisableAttack( void );
protected:
UnsignedInt m_dieFrame; ///< frame we die on
UnsignedInt m_tintEnvFadeFrames;///< param for tint envelope
UnsignedInt m_tintEnvPlayFrame;///< which frame to trigger the tint envelope
Real m_targetScale; ///How big will I get
//Real m_spinRate; ///HowMuch To Spin each frame;
Real m_currentScale; ///< how big I am drawing this frame
//static Bool s_lastInstanceSpunPositive;/// so that only every other instance spins positive direction
};
//-------------------------------------------------------------------------------------------------
class LeafletDropBehaviorModuleData : public UpdateModuleData
{
public:
UnsignedInt m_delayFrames;
UnsignedInt m_disabledDuration;
Real m_radius;
const ParticleSystemTemplate *m_leafletFXParticleSystem;
LeafletDropBehaviorModuleData()
{
m_delayFrames = 1;
m_disabledDuration = 0;
m_radius = 60.0f;
m_leafletFXParticleSystem = NULL;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "Delay", INI::parseDurationUnsignedInt, NULL, offsetof( LeafletDropBehaviorModuleData, m_delayFrames ) },
{ "DisabledDuration", INI::parseDurationUnsignedInt, NULL, offsetof( LeafletDropBehaviorModuleData, m_disabledDuration ) },
{ "AffectRadius", INI::parseReal, NULL, offsetof( LeafletDropBehaviorModuleData, m_radius ) },
{ "LeafletFXParticleSystem", INI::parseParticleSystemTemplate, NULL, offsetof( LeafletDropBehaviorModuleData, m_leafletFXParticleSystem ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class LeafletDropBehavior : public UpdateModule,
public DieModuleInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( LeafletDropBehavior, "LeafletDropBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( LeafletDropBehavior, LeafletDropBehaviorModuleData )
public:
LeafletDropBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update( void );
void doDisableAttack( void );
// BehaviorModule
virtual DieModuleInterface* getDie() { return this; }
// DieModuleInterface
virtual void onDie( const DamageInfo *damageInfo );
protected:
UnsignedInt m_startFrame; ///< frame we die on
Bool m_fxFired; ///< have we done our fx yet
};
#endif // __EMPUPDATE_H_

View file

@ -0,0 +1,77 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: EjectPilotDie.h /////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, April 2002
// Desc: Create object at current object's death
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _EjectPilotDie_H_
#define _EjectPilotDie_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/DieModule.h"
#include "Common/INI.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class ObjectCreationList;
//-------------------------------------------------------------------------------------------------
class EjectPilotDieModuleData : public DieModuleData
{
public:
const ObjectCreationList* m_oclInAir;
const ObjectCreationList* m_oclOnGround;
UnsignedInt m_invulnerableTime;
EjectPilotDieModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
/** When this object dies, create another object in its place */
//-------------------------------------------------------------------------------------------------
class EjectPilotDie : public DieModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( EjectPilotDie, "EjectPilotDie" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( EjectPilotDie, EjectPilotDieModuleData );
public:
EjectPilotDie( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
static void ejectPilot(const ObjectCreationList* ocl, const Object* dyingObject, const Object* damageDealer);
virtual void onDie( const DamageInfo *damageInfo );
virtual DieModuleInterface* getEjectPilotDieInterface( void ) {return this; }
};
#endif // _EjectPilotDie_H_

View file

@ -0,0 +1,89 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: EnemyNearUpdate.h /////////////////////////////////////////////////////////////////////////////
// Author: Matthew D. Campbell, April 2002
// Desc: Reacts when an enemy is within range
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __EnemyNearUpdate_H_
#define __EnemyNearUpdate_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
#include "Common/KindOf.h"
//-------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class EnemyNearUpdateModuleData : public UpdateModuleData
{
public:
UnsignedInt m_enemyScanDelayTime;
EnemyNearUpdateModuleData()
{
m_enemyScanDelayTime = LOGICFRAMES_PER_SECOND;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "ScanDelayTime", INI::parseDurationUnsignedInt, NULL, offsetof( EnemyNearUpdateModuleData, m_enemyScanDelayTime ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
}
};
//-------------------------------------------------------------------------------------------------
/** EnemyNear update */
//-------------------------------------------------------------------------------------------------
class EnemyNearUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( EnemyNearUpdate, "EnemyNearUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( EnemyNearUpdate, EnemyNearUpdateModuleData )
public:
EnemyNearUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update();
protected:
UnsignedInt m_enemyScanDelay;
Bool m_enemyNear;
void checkForEnemies( void );
};
#endif // end __EnemyNearUpdate_H_

View file

@ -0,0 +1,78 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ExperienceScalarUpgrade.h /////////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, September 2002
// Desc: UpgradeModule that adds a scalar to the object's experience gain.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __EXPERIENCE_SCALAR_UPGRADE_H_
#define __EXPERIENCE_SCALAR_UPGRADE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpgradeModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class ExperienceScalarUpgradeModuleData: public UpgradeModuleData
{
public:
ExperienceScalarUpgradeModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p);
Real m_addXPScalar;
};
//-------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class ExperienceScalarUpgrade : public UpgradeModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ExperienceScalarUpgrade, "ExperienceScalarUpgrade" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( ExperienceScalarUpgrade, ExperienceScalarUpgradeModuleData );
public:
ExperienceScalarUpgrade( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
protected:
virtual void upgradeImplementation( ); ///< Here's the actual work of Upgrading
virtual Bool isSubObjectsUpgrade() { return false; }
};
#endif // __DEFAULTDIE_H_

View file

@ -0,0 +1,136 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FXListDie.h /////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, Jan 2002
// Desc: Simple die module
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FXListDie_H_
#define __FXListDie_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/INI.h"
#include "GameLogic/Module/DieModule.h"
#include "GameLogic/Module/UpgradeModule.h"
#include "GameLogic/Weapon.h"
#include "GameLogic/Damage.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class FXList;
//-------------------------------------------------------------------------------------------------
class FXListDieModuleData : public DieModuleData
{
public:
const FXList *m_defaultDeathFX; ///< default fx to make
UpgradeMuxData m_upgradeMuxData;
Bool m_orientToObject;
Bool m_initiallyActive;
FXListDieModuleData()
{
m_defaultDeathFX = NULL;
m_orientToObject = TRUE;
m_initiallyActive = TRUE; //Patch 1.02 -- Craptacular HACK -- should default to FALSE but only ONE case sets it false out of 847!
}
static void buildFieldParse(MultiIniFieldParse& p)
{
DieModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "StartsActive", INI::parseBool, NULL, offsetof( FXListDieModuleData, m_initiallyActive ) },
{ "DeathFX", INI::parseFXList, NULL, offsetof( FXListDieModuleData, m_defaultDeathFX ) },
{ "OrientToObject", INI::parseBool, NULL, offsetof( FXListDieModuleData, m_orientToObject ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
p.add(UpgradeMuxData::getFieldParse(), offsetof( FXListDieModuleData, m_upgradeMuxData ));
}
};
//-------------------------------------------------------------------------------------------------
class FXListDie : public DieModule, public UpgradeMux
{
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FXListDie, FXListDieModuleData );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FXListDie, "FXListDie" )
public:
FXListDie( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// module methods
static Int getInterfaceMask() { return BehaviorModule::getInterfaceMask() | (MODULEINTERFACE_UPGRADE) | (MODULEINTERFACE_DIE); }
// BehaviorModule
virtual UpgradeModuleInterface* getUpgrade() { return this; }
virtual DieModuleInterface* getDie() { return this; }
virtual void onDie( const DamageInfo *damageInfo );
protected:
virtual void upgradeImplementation()
{
// nothing!
}
virtual void getUpgradeActivationMasks(UpgradeMaskType& activation, UpgradeMaskType& conflicting) const
{
getFXListDieModuleData()->m_upgradeMuxData.getUpgradeActivationMasks(activation, conflicting);
}
virtual void performUpgradeFX()
{
getFXListDieModuleData()->m_upgradeMuxData.performUpgradeFX(getObject());
}
virtual void processUpgradeRemoval()
{
// I can't take it any more. Let the record show that I think the UpgradeMux multiple inheritence is CRAP.
getFXListDieModuleData()->m_upgradeMuxData.muxDataProcessUpgradeRemoval(getObject());
}
virtual Bool requiresAllActivationUpgrades() const
{
return getFXListDieModuleData()->m_upgradeMuxData.m_requiresAllTriggers;
}
inline Bool isUpgradeActive() const { return isAlreadyUpgraded(); }
virtual Bool isSubObjectsUpgrade() { return false; }
};
#endif // __FXListDie_H_

View file

@ -0,0 +1,112 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FireOCLAfterWeaponCooldownUpdate.h ////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, September 2002
// Desc: This system tracks the objects status with regards to firing, and whenever the object stops
// firing, and all the conditions are met, then it'll create the specified OCL.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FIRE_OCL_AFTER_WEAPON_COOLDOWN_UPDATE_H
#define __FIRE_OCL_AFTER_WEAPON_COOLDOWN_UPDATE_H
class UpgradeMuxData;
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Module/UpgradeModule.h"
//-------------------------------------------------------------------------------------------------
class FireOCLAfterWeaponCooldownUpdateModuleData : public UpdateModuleData
{
public:
UpgradeMuxData m_upgradeMuxData;
ObjectCreationList *m_ocl;
WeaponSlotType m_weaponSlot;
UnsignedInt m_minShotsRequired;
UnsignedInt m_oclLifetimePerSecond;
UnsignedInt m_oclMaxFrames;
FireOCLAfterWeaponCooldownUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
class FireOCLAfterWeaponCooldownUpdate : public UpdateModule, public UpgradeMux
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FireOCLAfterWeaponCooldownUpdate, "FireOCLAfterWeaponCooldownUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FireOCLAfterWeaponCooldownUpdate, FireOCLAfterWeaponCooldownUpdateModuleData )
public:
FireOCLAfterWeaponCooldownUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// update methods
virtual UpdateSleepTime update(); ///< called once per frame
protected:
virtual void upgradeImplementation()
{
// nothing!
}
virtual void getUpgradeActivationMasks(UpgradeMaskType& activation, UpgradeMaskType& conflicting) const
{
getFireOCLAfterWeaponCooldownUpdateModuleData()->m_upgradeMuxData.getUpgradeActivationMasks(activation, conflicting);
}
virtual void performUpgradeFX()
{
getFireOCLAfterWeaponCooldownUpdateModuleData()->m_upgradeMuxData.performUpgradeFX(getObject());
}
virtual void processUpgradeRemoval()
{
// I can't take it any more. Let the record show that I think the UpgradeMux multiple inheritence is CRAP.
getFireOCLAfterWeaponCooldownUpdateModuleData()->m_upgradeMuxData.muxDataProcessUpgradeRemoval(getObject());
}
virtual Bool requiresAllActivationUpgrades() const
{
return getFireOCLAfterWeaponCooldownUpdateModuleData()->m_upgradeMuxData.m_requiresAllTriggers;
}
virtual Bool isSubObjectsUpgrade() { return false; }
void resetStats();
void fireOCL();
private:
Bool m_valid;
UnsignedInt m_consecutiveShots;
UnsignedInt m_startFrame;
};
#endif // __FIRE_OCL_AFTER_WEAPON_COOLDOWN_UPDATE_H

View file

@ -0,0 +1,81 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FireSpreadUpdate.h /////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, April 2002
// Desc: Update looks for ::Aflame and explicitly ignites someone nearby if set
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FIRE_SPREAD_UPDATE_H_
#define __FIRE_SPREAD_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
class ObjectCreationList;
//-------------------------------------------------------------------------------------------------
class FireSpreadUpdateModuleData : public UpdateModuleData
{
public:
const ObjectCreationList *m_oclEmbers;
UnsignedInt m_minSpreadTryDelayData;
UnsignedInt m_maxSpreadTryDelayData;
Real m_spreadTryRange;
FireSpreadUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class FireSpreadUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FireSpreadUpdate, "FireSpreadUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FireSpreadUpdate, FireSpreadUpdateModuleData )
public:
FireSpreadUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update();
void startFireSpreading();
protected:
UnsignedInt calcNextSpreadDelay();
};
#endif

View file

@ -0,0 +1,86 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FireWeaponCollide.h ///////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood April 2002
// Desc: Shoot something that collides with me every frame with my weapon
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FireWeaponCollide_H_
#define __FireWeaponCollide_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/CollideModule.h"
#include "GameLogic/Weapon.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Object;
//-------------------------------------------------------------------------------------------------
class FireWeaponCollideModuleData : public CollideModuleData
{
public:
const WeaponTemplate* m_collideWeaponTemplate;
ObjectStatusMaskType m_requiredStatus;
ObjectStatusMaskType m_forbiddenStatus;
Bool m_fireOnce;
FireWeaponCollideModuleData()
{
m_collideWeaponTemplate = NULL;
m_fireOnce = FALSE;
}
static void buildFieldParse(MultiIniFieldParse& p);
};
//-------------------------------------------------------------------------------------------------
class FireWeaponCollide : public CollideModule
{
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FireWeaponCollide, FireWeaponCollideModuleData );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FireWeaponCollide, "FireWeaponCollide" )
public:
FireWeaponCollide( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
protected:
virtual void onCollide( Object *other, const Coord3D *loc, const Coord3D *normal );
virtual Bool shouldFireWeapon();
private:
Weapon* m_collideWeapon;
Bool m_everFired;
};
#endif

View file

@ -0,0 +1,89 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FireWeaponPower.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Created: August 2003
//
// Filename: FireWeaponPower.h
//
// Author: Kris Morness
//
// Purpose: Simply loads and fires a specific weapon controlled by a superweapon timer.
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FIRE_WEAPON_POWER_H
#define __FIRE_WEAPON_POWER_H
#include "GameLogic/Module/SpecialPowerModule.h"
class Object;
class SpecialPowerTemplate;
struct FieldParse;
enum ScienceType;
class FireWeaponPowerModuleData : public SpecialPowerModuleData
{
public:
FireWeaponPowerModuleData( void );
static void buildFieldParse( MultiIniFieldParse& p );
UnsignedInt m_maxShotsToFire;
};
//-------------------------------------------------------------------------------------------------
class FireWeaponPower : public SpecialPowerModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FireWeaponPower, "FireWeaponPower" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FireWeaponPower, FireWeaponPowerModuleData )
public:
FireWeaponPower( Thing *thing, const ModuleData *moduleData );
virtual void doSpecialPower( UnsignedInt commandOptions );
virtual void doSpecialPowerAtLocation( const Coord3D *loc, Real angle, UnsignedInt commandOptions );
virtual void doSpecialPowerAtObject( Object *obj, UnsignedInt commandOptions );
protected:
};
#endif // __FIRE_WEAPON_POWER_H

View file

@ -0,0 +1,80 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FireWeaponUpdate.h /////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, August 2002
// Desc: Update fires a weapon at its own feet as quickly as the weapon allows
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FIRE_WEAPON_UPDATE_H_
#define __FIRE_WEAPON_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Weapon.h"
//-------------------------------------------------------------------------------------------------
class FireWeaponUpdateModuleData : public UpdateModuleData
{
public:
const WeaponTemplate* m_weaponTemplate;
UnsignedInt m_initialDelayFrames;
UnsignedInt m_exclusiveWeaponDelay; ///< If non-zero, any other weapon having fired this recently will keep us from doing anything
FireWeaponUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class FireWeaponUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FireWeaponUpdate, "FireWeaponUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FireWeaponUpdate, FireWeaponUpdateModuleData )
public:
FireWeaponUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update();
protected:
Bool isOkayToFire();
Weapon* m_weapon;
UnsignedInt m_initialDelayFrame;
};
#endif

View file

@ -0,0 +1,178 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FireWeaponWhenDamagedBehavior.h /////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, June 2002
// Desc: Update that will count down a lifetime and destroy object when it reaches zero
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FireWeaponWhenDamagedBehavior_H_
#define __FireWeaponWhenDamagedBehavior_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/UpgradeModule.h"
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/Module/DamageModule.h"
#include "GameLogic/Weapon.h"
//-------------------------------------------------------------------------------------------------
class FireWeaponWhenDamagedBehaviorModuleData : public UpdateModuleData
{
public:
UpgradeMuxData m_upgradeMuxData;
Bool m_initiallyActive;
DamageTypeFlags m_damageTypes;
Real m_damageAmount;
const WeaponTemplate* m_reactionWeaponPristine;///< fire these weapons only when damage is received
const WeaponTemplate* m_reactionWeaponDamaged;
const WeaponTemplate* m_reactionWeaponReallyDamaged;
const WeaponTemplate* m_reactionWeaponRubble;
const WeaponTemplate* m_continuousWeaponPristine;///< fire these weapons continuously, versus just onDamage
const WeaponTemplate* m_continuousWeaponDamaged;
const WeaponTemplate* m_continuousWeaponReallyDamaged;
const WeaponTemplate* m_continuousWeaponRubble;
FireWeaponWhenDamagedBehaviorModuleData()
{
m_initiallyActive = false;
m_reactionWeaponPristine = NULL;
m_reactionWeaponDamaged = NULL;
m_reactionWeaponReallyDamaged = NULL;
m_reactionWeaponRubble = NULL;
m_continuousWeaponPristine = NULL;
m_continuousWeaponDamaged = NULL;
m_continuousWeaponReallyDamaged = NULL;
m_continuousWeaponRubble = NULL;
m_damageTypes = DAMAGE_TYPE_FLAGS_ALL;
m_damageAmount = 0;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
static const FieldParse dataFieldParse[] =
{
{ "StartsActive", INI::parseBool, NULL, offsetof( FireWeaponWhenDamagedBehaviorModuleData, m_initiallyActive ) },
{ "ReactionWeaponPristine", INI::parseWeaponTemplate, NULL, offsetof(FireWeaponWhenDamagedBehaviorModuleData, m_reactionWeaponPristine) },
{ "ReactionWeaponDamaged", INI::parseWeaponTemplate, NULL, offsetof(FireWeaponWhenDamagedBehaviorModuleData, m_reactionWeaponDamaged) },
{ "ReactionWeaponReallyDamaged", INI::parseWeaponTemplate, NULL, offsetof(FireWeaponWhenDamagedBehaviorModuleData, m_reactionWeaponReallyDamaged) },
{ "ReactionWeaponRubble", INI::parseWeaponTemplate, NULL, offsetof(FireWeaponWhenDamagedBehaviorModuleData, m_reactionWeaponRubble) },
{ "ContinuousWeaponPristine", INI::parseWeaponTemplate, NULL, offsetof(FireWeaponWhenDamagedBehaviorModuleData, m_continuousWeaponPristine) },
{ "ContinuousWeaponDamaged", INI::parseWeaponTemplate, NULL, offsetof(FireWeaponWhenDamagedBehaviorModuleData, m_continuousWeaponDamaged) },
{ "ContinuousWeaponReallyDamaged", INI::parseWeaponTemplate, NULL, offsetof(FireWeaponWhenDamagedBehaviorModuleData,m_continuousWeaponReallyDamaged) },
{ "ContinuousWeaponRubble", INI::parseWeaponTemplate, NULL, offsetof(FireWeaponWhenDamagedBehaviorModuleData, m_continuousWeaponRubble) },
{ "DamageTypes", INI::parseDamageTypeFlags, NULL, offsetof( FireWeaponWhenDamagedBehaviorModuleData, m_damageTypes ) },
{ "DamageAmount", INI::parseReal, NULL, offsetof( FireWeaponWhenDamagedBehaviorModuleData, m_damageAmount ) },
{ 0, 0, 0, 0 }
};
UpdateModuleData::buildFieldParse(p);
p.add(dataFieldParse);
p.add(UpgradeMuxData::getFieldParse(), offsetof( FireWeaponWhenDamagedBehaviorModuleData, m_upgradeMuxData ));
}
private:
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class FireWeaponWhenDamagedBehavior : public UpdateModule,
public UpgradeMux,
public DamageModuleInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FireWeaponWhenDamagedBehavior, "FireWeaponWhenDamagedBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FireWeaponWhenDamagedBehavior, FireWeaponWhenDamagedBehaviorModuleData )
public:
FireWeaponWhenDamagedBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// module methids
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | (MODULEINTERFACE_UPGRADE) | (MODULEINTERFACE_DAMAGE); }
// BehaviorModule
virtual UpgradeModuleInterface* getUpgrade() { return this; }
virtual DamageModuleInterface* getDamage() { return this; }
// DamageModuleInterface
virtual void onDamage( DamageInfo *damageInfo );
virtual void onHealing( DamageInfo *damageInfo ) { }
virtual void onBodyDamageStateChange(const DamageInfo* damageInfo, BodyDamageType oldState, BodyDamageType newState) { }
// UpdateModuleInterface
virtual UpdateSleepTime update();
protected:
virtual void upgradeImplementation()
{
setWakeFrame(getObject(), UPDATE_SLEEP_NONE);
}
virtual void getUpgradeActivationMasks(UpgradeMaskType& activation, UpgradeMaskType& conflicting) const
{
getFireWeaponWhenDamagedBehaviorModuleData()->m_upgradeMuxData.getUpgradeActivationMasks(activation, conflicting);
}
virtual void performUpgradeFX()
{
getFireWeaponWhenDamagedBehaviorModuleData()->m_upgradeMuxData.performUpgradeFX(getObject());
}
virtual void processUpgradeRemoval()
{
// I can't take it any more. Let the record show that I think the UpgradeMux multiple inheritence is CRAP.
getFireWeaponWhenDamagedBehaviorModuleData()->m_upgradeMuxData.muxDataProcessUpgradeRemoval(getObject());
}
virtual Bool requiresAllActivationUpgrades() const
{
return getFireWeaponWhenDamagedBehaviorModuleData()->m_upgradeMuxData.m_requiresAllTriggers;
}
inline Bool isUpgradeActive() const { return isAlreadyUpgraded(); }
virtual Bool isSubObjectsUpgrade() { return false; }
private:
Weapon *m_reactionWeaponPristine;
Weapon *m_reactionWeaponDamaged;
Weapon *m_reactionWeaponReallyDamaged;
Weapon *m_reactionWeaponRubble;
Weapon *m_continuousWeaponPristine;
Weapon *m_continuousWeaponDamaged;
Weapon *m_continuousWeaponReallyDamaged;
Weapon *m_continuousWeaponRubble;
};
#endif // __FireWeaponWhenDamagedBehavior_H_

View file

@ -0,0 +1,133 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FireWeaponWhenDeadBehavior.h /////////////////////////////////////////////////////////////////////////
// Author: Colin Day, December 2001
// Desc: Update that will count down a lifetime and destroy object when it reaches zero
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FireWeaponWhenDeadBehavior_H_
#define __FireWeaponWhenDeadBehavior_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/DieModule.h"
#include "GameLogic/Module/UpgradeModule.h"
//-------------------------------------------------------------------------------------------------
class FireWeaponWhenDeadBehaviorModuleData : public BehaviorModuleData
{
public:
UpgradeMuxData m_upgradeMuxData;
Bool m_initiallyActive;
DieMuxData m_dieMuxData;
const WeaponTemplate* m_deathWeapon; ///< fire this weapon when we are damaged
FireWeaponWhenDeadBehaviorModuleData()
{
m_initiallyActive = false;
m_deathWeapon = NULL;
}
static void buildFieldParse(MultiIniFieldParse& p)
{
static const FieldParse dataFieldParse[] =
{
{ "StartsActive", INI::parseBool, NULL, offsetof( FireWeaponWhenDeadBehaviorModuleData, m_initiallyActive ) },
{ "DeathWeapon", INI::parseWeaponTemplate, NULL, offsetof( FireWeaponWhenDeadBehaviorModuleData, m_deathWeapon ) },
{ 0, 0, 0, 0 }
};
BehaviorModuleData::buildFieldParse(p);
p.add(dataFieldParse);
p.add(UpgradeMuxData::getFieldParse(), offsetof( FireWeaponWhenDeadBehaviorModuleData, m_upgradeMuxData ));
p.add(DieMuxData::getFieldParse(), offsetof( FireWeaponWhenDeadBehaviorModuleData, m_dieMuxData ));
}
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class FireWeaponWhenDeadBehavior : public BehaviorModule,
public UpgradeMux,
public DieModuleInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FireWeaponWhenDeadBehavior, "FireWeaponWhenDeadBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FireWeaponWhenDeadBehavior, FireWeaponWhenDeadBehaviorModuleData )
public:
FireWeaponWhenDeadBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// module methods
static Int getInterfaceMask() { return BehaviorModule::getInterfaceMask() | (MODULEINTERFACE_UPGRADE) | (MODULEINTERFACE_DIE); }
// BehaviorModule
virtual UpgradeModuleInterface* getUpgrade() { return this; }
virtual DieModuleInterface* getDie() { return this; }
// DamageModuleInterface
virtual void onDie( const DamageInfo *damageInfo );
protected:
virtual void upgradeImplementation()
{
// nothing!
}
virtual void getUpgradeActivationMasks(UpgradeMaskType& activation, UpgradeMaskType& conflicting) const
{
getFireWeaponWhenDeadBehaviorModuleData()->m_upgradeMuxData.getUpgradeActivationMasks(activation, conflicting);
}
virtual void performUpgradeFX()
{
getFireWeaponWhenDeadBehaviorModuleData()->m_upgradeMuxData.performUpgradeFX(getObject());
}
virtual void processUpgradeRemoval()
{
// I can't take it any more. Let the record show that I think the UpgradeMux multiple inheritence is CRAP.
getFireWeaponWhenDeadBehaviorModuleData()->m_upgradeMuxData.muxDataProcessUpgradeRemoval(getObject());
}
virtual Bool requiresAllActivationUpgrades() const
{
return getFireWeaponWhenDeadBehaviorModuleData()->m_upgradeMuxData.m_requiresAllTriggers;
}
inline Bool isUpgradeActive() const { return isAlreadyUpgraded(); }
virtual Bool isSubObjectsUpgrade() { return false; }
};
#endif // __FireWeaponWhenDeadBehavior_H_

View file

@ -0,0 +1,90 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FirestormDynamicGeometryInfoUpdate.h //////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, April 2002
// Desc: Update module adds the molestation of a particle system to Geometry changing
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FIRESTORM_DYNAMIC_GEOMETRY_INFO_UPDATE_H_
#define __FIRESTORM_DYNAMIC_GEOMETRY_INFO_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/Geometry.h"
#include "GameLogic/Module/DynamicGeometryInfoUpdate.h"
// ------------------------------------------------------------------------------------------------
enum { MAX_FIRESTORM_SYSTEMS = 16 };
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class ParticleSystemTemplate;
class FirestormDynamicGeometryInfoUpdateModuleData : public DynamicGeometryInfoUpdateModuleData
{
public:
FirestormDynamicGeometryInfoUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
const FXList *m_fxList;
const ParticleSystemTemplate *m_particleSystem[ MAX_FIRESTORM_SYSTEMS ];
Real m_particleOffsetZ;
Real m_scorchSize;
Real m_delayBetweenDamageFrames;
Real m_damageAmount;
Real m_maxHeightForDamage; // things higher than this above us take no damage
};
//-------------------------------------------------------------------------------------------------
/** The default update module */
//-------------------------------------------------------------------------------------------------
class FirestormDynamicGeometryInfoUpdate : public DynamicGeometryInfoUpdate
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FirestormDynamicGeometryInfoUpdate, "FirestormDynamicGeometryInfoUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FirestormDynamicGeometryInfoUpdate, FirestormDynamicGeometryInfoUpdateModuleData );
public:
FirestormDynamicGeometryInfoUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update();
protected:
void doDamageScan( void );
ParticleSystemID m_myParticleSystemID[ MAX_FIRESTORM_SYSTEMS ];
Bool m_effectsFired; ///< TRUE once the effects have been fired off
Bool m_scorchPlaced; ///< TRUE once we have placed the scorch mark
UnsignedInt m_lastDamageFrame; ///< frame we last did damage on
};
#endif

View file

@ -0,0 +1,120 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FlammableUpdate.h /////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood, April 2002
// Desc: Update that manages Aflame and Burned statuses and their effects
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FLAMMABLE_UPDATE_H_
#define __FLAMMABLE_UPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/AudioEventRTS.h"
#include "GameLogic/Module/DamageModule.h"
#include "GameLogic/Module/UpdateModule.h"
//-------------------------------------------------------------------------------------------------
enum FlammabilityStatusType
{
// These show the state I last noticed my object was in.
FS_NORMAL = 0,
FS_AFLAME,
FS_BURNED,
FS_NORMAL_COUNT // keep last
};
//-------------------------------------------------------------------------------------------------
class FlammableUpdateModuleData : public UpdateModuleData
{
public:
UnsignedInt m_burnedDelay; ///< How long before I am ::Burned. 0 means never
UnsignedInt m_aflameDuration; ///< How long I stay ::Aflame. Independent of Burned.
// When aflame wears out is when I check to be normal or burned, So my model can
// change to burned while I am still aflame.
UnsignedInt m_aflameDamageDelay; ///< While ::Aflame, I take damage this often. If 0, never.
Int m_aflameDamageAmount; ///< And this is how much I take.
AsciiString m_burningSoundName; ///< Sound to loop-play while burning (Not an AudioEventRTS here, since that belongs to the module)
Real m_flameDamageLimitData;
UnsignedInt m_flameDamageExpirationDelay;
FlammableUpdateModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class FlammableUpdate : public UpdateModule, public DamageModuleInterface
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FlammableUpdate, "FlammableUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FlammableUpdate, FlammableUpdateModuleData )
public:
FlammableUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | (MODULEINTERFACE_DAMAGE); }
virtual DamageModuleInterface* getDamage() { return this; }
void tryToIgnite(); ///< FlammabeDamage uses this. It is up to me to decide if I am burnable
Bool wouldIgnite(); ///< Since we need to cheat sometimes and light something directly, ask if this would light
//UpdateModuleInterface
virtual UpdateSleepTime update();
//DamageModuleInterface
virtual void onDamage( DamageInfo *damageInfo );
virtual void onHealing( DamageInfo *damageInfo ) { }
virtual void onBodyDamageStateChange( const DamageInfo *damageInfo,
BodyDamageType oldState,
BodyDamageType newState ) { }
protected:
UpdateSleepTime calcSleepTime();
void doAflameDamage();
void startBurningSound();
void stopBurningSound();
FlammabilityStatusType m_status;
UnsignedInt m_aflameEndFrame;
UnsignedInt m_burnedEndFrame;
UnsignedInt m_damageEndFrame;
AudioHandle m_audioHandle;
Real m_flameDamageLimit;
UnsignedInt m_lastFlameDamageDealt;
};
#endif

View file

@ -0,0 +1,233 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (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<AsciiString> m_spacesBoneNames;
std::vector<AsciiString> m_taxiBoneNames;
std::vector<AsciiString> 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<Coord3D>* getTaxiLocations( ObjectID id ) const;
virtual const std::vector<Coord3D>* 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<Coord3D> m_taxi;
std::vector<Coord3D> 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<FlightDeckInfo> m_spaces;
std::vector<RunwayInfo> m_runways;
std::list<HealingInfo> 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

View file

@ -0,0 +1,78 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FloatUpdate.h ////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, May 2002
// Desc: Floting on water update
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FLOATUPDATE_H_
#define __FLOATUPDATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/UpdateModule.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
struct FieldParse;
//-------------------------------------------------------------------------------------------------
class FloatUpdateModuleData: public UpdateModuleData
{
public:
FloatUpdateModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p);
Bool m_enabled; ///< enabled
};
//-------------------------------------------------------------------------------------------------
class FloatUpdate : public UpdateModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FloatUpdate, "FloatUpdate" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FloatUpdate, FloatUpdateModuleData )
public:
FloatUpdate( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
void setEnabled( Bool enabled ) { m_enabled = enabled; } ///< enable/disable floating
virtual UpdateSleepTime update(); ///< Deciding whether or not to make new guys
protected:
Bool m_enabled; ///< enabled
};
#endif // end __FLOATUPDATE_H_

View file

@ -0,0 +1,249 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GarrisonContain.h ////////////////////////////////////////////////////////////////////////
// Author: Colin Day, February 2002
// Desc: Contain module for structures that can be garrisoned
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __GARRISONCONTAIN_H_
#define __GARRISONCONTAIN_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/OpenContain.h"
#include "Common/ModelState.h"
//-------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class GarrisonContainModuleData : public OpenContainModuleData
{
public:
struct InitialRoster
{
AsciiString templateName;
Int count;
};
Bool m_doIHealObjects;
Real m_framesForFullHeal;
Bool m_mobileGarrison;
Bool m_immuneToClearBuildingAttacks;
Bool m_isEnclosingContainer;
InitialRoster m_initialRoster;
GarrisonContainModuleData( void );
static void buildFieldParse(MultiIniFieldParse& p)
{
OpenContainModuleData::buildFieldParse(p);
static const FieldParse dataFieldParse[] =
{
{ "MobileGarrison", INI::parseBool, NULL, offsetof( GarrisonContainModuleData, m_mobileGarrison ) },
{ "HealObjects", INI::parseBool, NULL, offsetof( GarrisonContainModuleData, m_doIHealObjects ) },
{ "TimeForFullHeal", INI::parseDurationReal, NULL, offsetof( GarrisonContainModuleData, m_framesForFullHeal ) },
{ "InitialRoster", parseInitialRoster, NULL, 0 },
{ "ImmuneToClearBuildingAttacks", INI::parseBool, NULL, offsetof( GarrisonContainModuleData, m_immuneToClearBuildingAttacks ) },
{ "IsEnclosingContainer", INI::parseBool, NULL, offsetof( GarrisonContainModuleData, m_isEnclosingContainer ) },
{ 0, 0, 0, 0 }
};
p.add(dataFieldParse);
};
static void parseInitialRoster( INI* ini, void *instance, void *store, const void* )
{
GarrisonContainModuleData* self = (GarrisonContainModuleData*)instance;
const char* name = ini->getNextToken();
const char* countStr = ini->getNextTokenOrNull();
Int count = countStr ? INI::scanInt(countStr) : 1;
self->m_initialRoster.templateName.set(name);
self->m_initialRoster.count = count;
};
};
//-------------------------------------------------------------------------------------------------
/** A GarrisonContain is used for objects that can be garrisoned, heh, go figure */
//-------------------------------------------------------------------------------------------------
class GarrisonContain : public OpenContain
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( GarrisonContain, "GarrisonContain" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( GarrisonContain, GarrisonContainModuleData )
public:
GarrisonContain( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
virtual UpdateSleepTime update( void ); ///< called once per frame
virtual Bool isValidContainerFor( const Object* obj, Bool checkCapacity) const; // Garrison has an extra check forbidding any containment if ReallyDamaged
virtual Bool isGarrisonable() const { return true; } ///< can this unit be Garrisoned? (ick)
virtual Bool isBustable() const { return TRUE; } ///< can this container get busted by a bunkerbuster
virtual Bool isImmuneToClearBuildingAttacks() const { return getGarrisonContainModuleData()->m_immuneToClearBuildingAttacks; }
virtual Bool isHealContain() const { return false; } ///< true when container only contains units while healing (not a transport!)
virtual Bool isTunnelContain() const { return FALSE; }
virtual Bool isPassengerAllowedToFire( ObjectID id = INVALID_ID ) const; ///< Hey, can I shoot out of this container?
virtual Bool isEnclosingContainerFor( const Object *obj ) const { return getGarrisonContainModuleData()->m_isEnclosingContainer; }
virtual Bool isSpecialOverlordStyleContainer() const {return FALSE;}
virtual void removeAllContained( Bool exposeStealthUnits ); ///< remove all contents of this open container
virtual void exitObjectViaDoor( Object *exitObj, ExitDoorType exitDoor ); ///< exit one of our content items from us
virtual void exitObjectByBudding( Object *newObj, Object *budHost ) { return; };
virtual void onContaining( Object *obj, Bool wasSelected ); ///< object now contains 'obj'
virtual void onRemoving( Object *obj ); ///< object no longer contains 'obj'
virtual void onSelling( void );
// A Garrison Contain must eject all passengers when it crosses the ReallyDamaged threshold.
virtual void onBodyDamageStateChange( const DamageInfo* damageInfo,
BodyDamageType oldState,
BodyDamageType newState); ///< Die Interface state change callback
/**
return the player that *appears* to control this unit, given an observing player.
if null, use getObject()->getControllingPlayer() instead.
*/
virtual const Player* getApparentControllingPlayer( const Player* observingPlayer ) const;
virtual void recalcApparentControllingPlayer( void );
virtual Bool isDisplayedOnControlBar() const {return TRUE;}///< Does this container display its contents on the ControlBar?
virtual void onDamage( DamageInfo *info );
virtual void setEvacDisposition( EvacDisposition disp ) { m_evacDisposition = disp; };
protected:
virtual void redeployOccupants( void ); ///< redeploy the occupants of us at all available garrison points
virtual void onObjectCreated();
void validateRallyPoint( void ); ///< validate (if necessary) and pick (if possible) an exit rally point
virtual Bool calcBestGarrisonPosition( Coord3D *sourcePos, const Coord3D *targetPos );
virtual Bool attemptBestFirePointPosition( Object *source, Weapon *weapon, Object *victim );
virtual Bool attemptBestFirePointPosition( Object *source, Weapon *weapon, const Coord3D *targetPos );
void updateEffects( void ); ///< do any effects needed per frame
void loadGarrisonPoints( void ); ///< load garrison point position data and save for later
void putObjectAtBestGarrisonPoint( Object *obj, Object *target, const Coord3D *targetPos ); ///< place object at position of the best garrison point to use for its target
void putObjectAtGarrisonPoint( Object *obj, ObjectID targetID, Int conditionIndex, Int index ); ///< place object at the specified garrison point index
enum { SEARCH_FOR_REMOVE = -1 };
void removeObjectFromGarrisonPoint( Object *obj, Int index = SEARCH_FOR_REMOVE );///< remove object from the garrison point placement
void addValidObjectsToGarrisonPoints( void ); ///< add any objects with targets to a garrison point
void removeInvalidObjectsFromGarrisonPoints( void ); ///< remove objects with invalid targets from valid points
void trackTargets( void ); ///< keep attackers at the closest garrison point to their active target
void matchObjectsToGarrisonPoints( void ); ///< Every frame, and whenever anyone enters or leaves
void positionObjectsAtStationGarrisonPoints( void ); ///< enforce that everybody stays at their pre-assigned space
void loadStationGarrisonPoints( void );
Bool pickAStationForMe( const Object *pbj );
void removeObjectFromStationPoint( const Object *obj );
enum { GARRISON_INDEX_INVALID = -1 };
Int findConditionIndex( void ); ///< find the condition index to use given the current object body state
Int getObjectGarrisonPointIndex( Object *obj ); ///< get the garrison point index object is at (if present)
Int findClosestFreeGarrisonPointIndex( Int conditionIndex,
const Coord3D *targetPos ); ///< find closest free garrison point to the target location
void healObjects( void ); ///< heal all the objects within me
void healSingleObject( Object *obj, Real frames ); ///< heal just one of the objects within me
void moveObjectsWithMe( void ); ///< translates all the garrisoned object to this->getObject()->getPosition()
private:
enum { MAX_GARRISON_POINTS = 40 };
//
// The max units inside any garrisoned structure is 10. Since the units will "move around"
// the inside of the structure to be close to their targets, we need a max of 10 garrison points
// on each side of the building to accomodate everybody inside
//
// ----------------------------------------------------------------------------------------------
struct GarrisonPointData
{
union
{
Object * object; ///< object at this garrison point
ObjectID objectID; ///< for loading
};
ObjectID targetID; ///< object ID that is our current target
UnsignedInt placeFrame; ///< frame we were placed at this garrison point
UnsignedInt lastEffectFrame; ///< last frame we fired our effects on
union
{
Drawable * effect; ///< effect object for showing gun barrels and muzzle flash fire
DrawableID effectID; ///< for loading
};
};
struct StationPointData
{
ObjectID occupantID;
Coord3D position;
};
// ----------------------------------------------------------------------------------------------
enum
{
GARRISON_POINT_PRISTINE,
GARRISON_POINT_DAMAGED,
GARRISON_POINT_REALLY_DAMAGED,
MAX_GARRISON_POINT_CONDITIONS ///< leave this last
};
Team * m_originalTeam; ///< our original team before we were garrisoned
GarrisonPointData m_garrisonPointData[ MAX_GARRISON_POINTS ]; ///< the garrison point placement data
Int m_garrisonPointsInUse;
Coord3D m_garrisonPoint[ MAX_GARRISON_POINT_CONDITIONS ][ MAX_GARRISON_POINTS ]; ///< the garrison point positions (in world coords) for pristine, damaged, and really damaged
Coord3D m_exitRallyPoint; ///< Point to rally at when exiting structure (if possible)
std::vector<StationPointData> m_stationPointList;
Bool m_stationGarrisonPointsInitialized; ///< DO NOT XFER THIS!!! TRUE once we have loaded the pre-assigned garrison point positions from the art
Bool m_garrisonPointsInitialized; ///< TRUE once we have loaded the garrison point positions from the art
Bool m_hideGarrisonedStateFromNonallies; ///< if T, don't appear to be garrisoned (all stealthy)
Bool m_rallyValid; ///< TRUE when m_exitRallyPoint is valid
EvacDisposition m_evacDisposition;
};
#endif // __GARRISONCONTAIN_H_

View file

@ -0,0 +1,139 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GenerateMinefieldBehavior.h /////////////////////////////////////////////////////////////////////////
// Author: Colin Day, December 2001
// Desc: Update that will count down a lifetime and destroy object when it reaches zero
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __GenerateMinefieldBehavior_H_
#define __GenerateMinefieldBehavior_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/BehaviorModule.h"
#include "GameLogic/Module/DieModule.h"
#include "GameLogic/Module/UpgradeModule.h"
#include "GameLogic/Module/UpdateModule.h"
//-------------------------------------------------------------------------------------------------
class GenerateMinefieldBehaviorModuleData : public BehaviorModuleData
{
public:
UpgradeMuxData m_upgradeMuxData;
AsciiString m_mineName;
AsciiString m_mineNameUpgraded;
AsciiString m_mineUpgradeTrigger;
const FXList* m_genFX;
Real m_distanceAroundObject;
Real m_minesPerSquareFoot;
Real m_randomJitter;
Real m_skipIfThisMuchUnderStructure;
Bool m_onDeath;
Bool m_borderOnly;
Bool m_alwaysCircular;
Bool m_upgradable;
Bool m_smartBorder;
Bool m_smartBorderSkipInterior;
GenerateMinefieldBehaviorModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
private:
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class GenerateMinefieldBehavior : public UpdateModule,
public DieModuleInterface,
public UpgradeMux
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( GenerateMinefieldBehavior, "GenerateMinefieldBehavior" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( GenerateMinefieldBehavior, GenerateMinefieldBehaviorModuleData )
public:
GenerateMinefieldBehavior( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration
// module methods
static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | (MODULEINTERFACE_DIE) | (MODULEINTERFACE_UPGRADE); }
// BehaviorModule
virtual DieModuleInterface* getDie() { return this; }
virtual UpgradeModuleInterface* getUpgrade() { return this; }
virtual UpdateSleepTime update();
// DamageModuleInterface
virtual void onDie( const DamageInfo *damageInfo );
void setMinefieldTarget(const Coord3D* pos);
protected:
virtual void upgradeImplementation();
virtual Bool isSubObjectsUpgrade() { return false; }
virtual void getUpgradeActivationMasks(UpgradeMaskType& activation, UpgradeMaskType& conflicting) const
{
getGenerateMinefieldBehaviorModuleData()->m_upgradeMuxData.getUpgradeActivationMasks(activation, conflicting);
}
virtual void performUpgradeFX()
{
getGenerateMinefieldBehaviorModuleData()->m_upgradeMuxData.performUpgradeFX(getObject());
}
virtual void processUpgradeRemoval()
{
// I can't take it any more. Let the record show that I think the UpgradeMux multiple inheritence is CRAP.
getGenerateMinefieldBehaviorModuleData()->m_upgradeMuxData.muxDataProcessUpgradeRemoval(getObject());
}
virtual Bool requiresAllActivationUpgrades() const
{
return getGenerateMinefieldBehaviorModuleData()->m_upgradeMuxData.m_requiresAllTriggers;
}
private:
Coord3D m_target;
Bool m_hasTarget;
Bool m_generated;
Bool m_upgraded;
std::list<ObjectID> m_mineList;
const Coord3D* getMinefieldTarget() const;
void placeMines();
void placeMinesInFootprint(const GeometryInfo& geom, const ThingTemplate* mineTemplate);
void placeMinesAroundCircle(const Coord3D& pos, Real radius, const ThingTemplate* mineTemplate);
void placeMinesAlongLine(const Coord3D& posStart, const Coord3D& posEnd, const ThingTemplate* mineTemplate, Bool skipOneAtStart);
void placeMinesAroundRect(const Coord3D& pos, Real majorRadius, Real minorRadius, const ThingTemplate* mineTemplate);
Object* placeMineAt(const Coord3D& pt, const ThingTemplate* mineTemplate, Team* team, const Object* producer);
};
#endif // __GenerateMinefieldBehavior_H_

View file

@ -0,0 +1,87 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GrantScienceUpgrade.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Los Angeles
//
// Confidential Information
// Copyright (C) 2003 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Created: August 2, 2003
//
// Filename: GrantScienceUpgrade.cpp
//
// Author: Kris Morness
//
// Purpose: Grants specified science once requirements met (typically an upgrade).
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __GRANT_SCIENCE_UPGRADE_H
#define __GRANT_SCIENCE_UPGRADE_H
#include "GameLogic/Module/UpgradeModule.h"
//-----------------------------------------------------------------------------
class GrantScienceUpgradeModuleData : public UpgradeModuleData
{
public:
AsciiString m_grantScienceName;
GrantScienceUpgradeModuleData(){}
static void buildFieldParse(MultiIniFieldParse& p);
};
//-----------------------------------------------------------------------------
class GrantScienceUpgrade : public UpgradeModule
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( GrantScienceUpgrade, "GrantScienceUpgrade" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( GrantScienceUpgrade, GrantScienceUpgradeModuleData );
public:
GrantScienceUpgrade( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
protected:
virtual void upgradeImplementation( ); ///< Here's the actual work of Upgrading
virtual Bool isSubObjectsUpgrade() { return false; }
private:
ScienceType m_scienceType;
};
#endif // _COMMAND_SET_UPGRADE_H

Some files were not shown because too many files have changed in this diff Show more