Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
491
Generals/Code/GameEngine/Include/Common/GameCommon.h
Normal file
491
Generals/Code/GameEngine/Include/Common/GameCommon.h
Normal file
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
** Command & Conquer Generals(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: GameCommon.h ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: GameCommon.h
|
||||
//
|
||||
// Created: Steven Johnson, October 2001
|
||||
//
|
||||
// Desc: This is a catchall header for some basic types and definitions
|
||||
// needed by various bits of the GameLogic/GameClient, but that
|
||||
// we haven't found a good place for yet. Hopefully this file
|
||||
// should go away someday, but for now is a convenient spot.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _GAMECOMMON_H_
|
||||
#define _GAMECOMMON_H_
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
#include "Lib/BaseType.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
#if defined(_INTERNAL) || defined(_DEBUG) || defined(_PLAYTEST)
|
||||
#define NO_DUMP_PERF_STATS
|
||||
#else
|
||||
#define NO_DUMP_PERF_STATS
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
enum
|
||||
{
|
||||
LOGICFRAMES_PER_SECOND = 30,
|
||||
MSEC_PER_SECOND = 1000
|
||||
};
|
||||
const Real LOGICFRAMES_PER_MSEC_REAL = (((Real)LOGICFRAMES_PER_SECOND) / ((Real)MSEC_PER_SECOND));
|
||||
const Real MSEC_PER_LOGICFRAME_REAL = (((Real)MSEC_PER_SECOND) / ((Real)LOGICFRAMES_PER_SECOND));
|
||||
const Real LOGICFRAMES_PER_SECONDS_REAL = (Real)LOGICFRAMES_PER_SECOND;
|
||||
const Real SECONDS_PER_LOGICFRAME_REAL = 1.0f / LOGICFRAMES_PER_SECONDS_REAL;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// note that this returns a REAL value, not an int... most callers will want to
|
||||
// call ceil() on the result, so that partial frames get converted to full frames!
|
||||
inline Real ConvertDurationFromMsecsToFrames(Real msec)
|
||||
{
|
||||
return (msec * LOGICFRAMES_PER_MSEC_REAL);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
inline Real ConvertVelocityInSecsToFrames(Real distPerMsec)
|
||||
{
|
||||
// this looks wrong, but is the correct conversion factor.
|
||||
return (distPerMsec * SECONDS_PER_LOGICFRAME_REAL);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
inline Real ConvertAccelerationInSecsToFrames(Real distPerSec2)
|
||||
{
|
||||
// this looks wrong, but is the correct conversion factor.
|
||||
const Real SEC_PER_LOGICFRAME_SQR = (SECONDS_PER_LOGICFRAME_REAL * SECONDS_PER_LOGICFRAME_REAL);
|
||||
return (distPerSec2 * SEC_PER_LOGICFRAME_SQR);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
inline Real ConvertAngularVelocityInDegreesPerSecToRadsPerFrame(Real degPerSec)
|
||||
{
|
||||
const Real RADS_PER_DEGREE = PI / 180.0f;
|
||||
return (degPerSec * (SECONDS_PER_LOGICFRAME_REAL * RADS_PER_DEGREE));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
enum
|
||||
{
|
||||
MAX_PLAYER_COUNT = 16 ///< max number of Players.
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
/**
|
||||
a bitmask that can uniquely represent each player.
|
||||
*/
|
||||
#if MAX_PLAYER_COUNT <= 16
|
||||
typedef UnsignedShort PlayerMaskType;
|
||||
const PlayerMaskType PLAYERMASK_ALL = 0xffff;
|
||||
const PlayerMaskType PLAYERMASK_NONE = 0x0;
|
||||
#else
|
||||
#error "this is the wrong size"
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
enum GameDifficulty
|
||||
{
|
||||
DIFFICULTY_EASY,
|
||||
DIFFICULTY_NORMAL,
|
||||
DIFFICULTY_HARD,
|
||||
|
||||
DIFFICULTY_COUNT
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
enum PlayerType
|
||||
{
|
||||
PLAYER_HUMAN, ///< player is human-controlled
|
||||
PLAYER_COMPUTER, ///< player is computer-controlled
|
||||
|
||||
PLAYERTYPE_COUNT
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/// A PartitionCell can be one of three states for Shroud
|
||||
enum CellShroudStatus
|
||||
{
|
||||
CELLSHROUD_CLEAR,
|
||||
CELLSHROUD_FOGGED,
|
||||
CELLSHROUD_SHROUDED,
|
||||
|
||||
CELLSHROUD_COUNT
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/// Since an object can take up more than a single PartitionCell, this is a status that applies to the whole Object
|
||||
enum ObjectShroudStatus
|
||||
{
|
||||
OBJECTSHROUD_INVALID, ///< indeterminate state, will recompute
|
||||
OBJECTSHROUD_CLEAR, ///< object is not shrouded at all (ie, completely visible)
|
||||
OBJECTSHROUD_PARTIAL_CLEAR, ///< object is partly clear (rest is shroud or fog)
|
||||
OBJECTSHROUD_FOGGED, ///< object is completely fogged
|
||||
OBJECTSHROUD_SHROUDED, ///< object is completely shrouded
|
||||
OBJECTSHROUD_INVALID_BUT_PREVIOUS_VALID, ///< indeterminate state, will recompute, BUT previous status is valid, don't reset (used for save/load)
|
||||
|
||||
OBJECTSHROUD_COUNT
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
enum GuardMode
|
||||
{
|
||||
GUARDMODE_NORMAL,
|
||||
GUARDMODE_GUARD_WITHOUT_PURSUIT, // no pursuit out of guard area
|
||||
GUARDMODE_GUARD_FLYING_UNITS_ONLY // ignore nonflyers
|
||||
};
|
||||
|
||||
// ---------------------------------------------------
|
||||
enum
|
||||
{
|
||||
NEVER = 0,
|
||||
FOREVER = 0x3fffffff // (we use 0x3fffffff so that we can add offsets and not overflow...
|
||||
// at 30fps we're still pretty safe!)
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
/// Veterancy level define needed by several files that don't need the full Experience code.
|
||||
// NOTE NOTE NOTE: Keep TheVeterencyNames in sync with these.
|
||||
enum VeterancyLevel
|
||||
{
|
||||
LEVEL_REGULAR = 0,
|
||||
LEVEL_VETERAN,
|
||||
LEVEL_ELITE,
|
||||
LEVEL_HEROIC,
|
||||
|
||||
LEVEL_COUNT,
|
||||
LEVEL_INVALID,
|
||||
|
||||
LEVEL_FIRST = LEVEL_REGULAR,
|
||||
LEVEL_LAST = LEVEL_HEROIC
|
||||
};
|
||||
|
||||
// TheVeterancyNames is defined in GameCommon.cpp
|
||||
extern const char *TheVeterancyNames[];
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
enum CommandSourceType
|
||||
{
|
||||
|
||||
CMD_FROM_PLAYER = 0,
|
||||
CMD_FROM_SCRIPT,
|
||||
CMD_FROM_AI,
|
||||
CMD_FROM_DOZER, // Special rare command when the dozer originates a command to attack a mine. Mines are not ai-attackable, and it seems deceitful for the dozer to generate a player or script command. jba.
|
||||
|
||||
}; ///< the source of a command
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
enum AbleToAttackType
|
||||
{
|
||||
_ATTACK_FORCED = 0x01,
|
||||
_ATTACK_CONTINUED = 0x02,
|
||||
_ATTACK_TUNNELNETWORK_GUARD = 0x04,
|
||||
|
||||
/**
|
||||
can we attack if this is a new target?
|
||||
*/
|
||||
ATTACK_NEW_TARGET = (0),
|
||||
|
||||
/**
|
||||
can we attack if this is a new target, via force-fire?
|
||||
(The only current difference between this and ATTACK_NEW_TARGET is that disguised units
|
||||
are force-attackable even when stealthed.)
|
||||
*/
|
||||
ATTACK_NEW_TARGET_FORCED= (_ATTACK_FORCED),
|
||||
|
||||
/**
|
||||
can we attack if this is continuation of an existing attack?
|
||||
(The only current difference between this and ATTACK_NEW_TARGET is you are allowed to follow
|
||||
immobile shrouded units into the fog)
|
||||
*/
|
||||
ATTACK_CONTINUED_TARGET = (_ATTACK_CONTINUED),
|
||||
|
||||
/**
|
||||
can we attack if this is continuation of an existing attack?
|
||||
(The only current difference between this and ATTACK_NEW_TARGET is you are allowed to follow
|
||||
immobile shrouded units into the fog)
|
||||
*/
|
||||
ATTACK_CONTINUED_TARGET_FORCED = (_ATTACK_FORCED | _ATTACK_CONTINUED),
|
||||
|
||||
/**
|
||||
Special case that bypasses some of the checks for units guarding from within tunnel networks!
|
||||
For example, a unit inside couldn't normally see outside and would fail.
|
||||
*/
|
||||
ATTACK_TUNNEL_NETWORK_GUARD = (_ATTACK_TUNNELNETWORK_GUARD)
|
||||
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
inline Bool isForcedAttack(AbleToAttackType t)
|
||||
{
|
||||
return (((Int)t) & _ATTACK_FORCED) != 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
inline Bool isContinuedAttack(AbleToAttackType t)
|
||||
{
|
||||
return (((Int)t) & _ATTACK_CONTINUED) != 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
typedef UnsignedInt VeterancyLevelFlags;
|
||||
|
||||
const VeterancyLevelFlags VETERANCY_LEVEL_FLAGS_ALL = 0xffffffff;
|
||||
const VeterancyLevelFlags VETERANCY_LEVEL_FLAGS_NONE = 0x00000000;
|
||||
|
||||
inline Bool getVeterancyLevelFlag(VeterancyLevelFlags flags, VeterancyLevel dt)
|
||||
{
|
||||
return (flags & (1UL << (dt - 1))) != 0;
|
||||
}
|
||||
|
||||
inline VeterancyLevelFlags setVeterancyLevelFlag(VeterancyLevelFlags flags, VeterancyLevel dt)
|
||||
{
|
||||
return (flags | (1UL << (dt - 1)));
|
||||
}
|
||||
|
||||
inline VeterancyLevelFlags clearVeterancyLevelFlag(VeterancyLevelFlags flags, VeterancyLevel dt)
|
||||
{
|
||||
return (flags & ~(1UL << (dt - 1)));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
#define BOGUSPTR(p) ((((unsigned int)(p)) & 1) != 0)
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
#define MAKE_DLINK_HEAD(OBJCLASS, LISTNAME) \
|
||||
public: \
|
||||
inline DLINK_ITERATOR<OBJCLASS> iterate_##LISTNAME() const \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
|
||||
return DLINK_ITERATOR<OBJCLASS>(m_dlinkhead_##LISTNAME.m_head, OBJCLASS::dlink_next_##LISTNAME); \
|
||||
} \
|
||||
inline OBJCLASS *getFirstItemIn_##LISTNAME() const \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
|
||||
return m_dlinkhead_##LISTNAME.m_head; \
|
||||
} \
|
||||
inline Bool isInList_##LISTNAME(OBJCLASS* o) const \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
|
||||
return o->dlink_isInList_##LISTNAME(&m_dlinkhead_##LISTNAME.m_head); \
|
||||
} \
|
||||
inline void prependTo_##LISTNAME(OBJCLASS* o) \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
|
||||
if (!isInList_##LISTNAME(o)) \
|
||||
o->dlink_prependTo_##LISTNAME(&m_dlinkhead_##LISTNAME.m_head); \
|
||||
} \
|
||||
inline void removeFrom_##LISTNAME(OBJCLASS* o) \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
|
||||
if (isInList_##LISTNAME(o)) \
|
||||
o->dlink_removeFrom_##LISTNAME(&m_dlinkhead_##LISTNAME.m_head); \
|
||||
} \
|
||||
typedef void (*RemoveAllProc_##LISTNAME)(OBJCLASS* o); \
|
||||
inline void removeAll_##LISTNAME(RemoveAllProc_##LISTNAME p = NULL) \
|
||||
{ \
|
||||
while (m_dlinkhead_##LISTNAME.m_head) \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr"));\
|
||||
OBJCLASS *tmp = m_dlinkhead_##LISTNAME.m_head; \
|
||||
removeFrom_##LISTNAME(tmp); \
|
||||
if (p) (*p)(tmp); \
|
||||
} \
|
||||
} \
|
||||
inline void reverse_##LISTNAME() \
|
||||
{ \
|
||||
OBJCLASS* cur = m_dlinkhead_##LISTNAME.m_head; \
|
||||
OBJCLASS* prev = NULL; \
|
||||
while (cur) \
|
||||
{ \
|
||||
OBJCLASS* originalNext = cur->dlink_next_##LISTNAME(); \
|
||||
cur->dlink_swapLinks_##LISTNAME(); \
|
||||
prev = cur; \
|
||||
cur = originalNext; \
|
||||
} \
|
||||
m_dlinkhead_##LISTNAME.m_head = prev; \
|
||||
} \
|
||||
private: \
|
||||
/* a trick: init head to zero */ \
|
||||
struct DLINKHEAD_##LISTNAME \
|
||||
{ \
|
||||
public: \
|
||||
OBJCLASS* m_head; \
|
||||
inline DLINKHEAD_##LISTNAME() : \
|
||||
m_head(0) { } \
|
||||
inline ~DLINKHEAD_##LISTNAME() \
|
||||
{ DEBUG_ASSERTCRASH(!m_head,("destroying dlinkhead still in a list " #LISTNAME)); } \
|
||||
}; \
|
||||
DLINKHEAD_##LISTNAME m_dlinkhead_##LISTNAME;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
#define MAKE_DLINK(OBJCLASS, LISTNAME) \
|
||||
public: \
|
||||
OBJCLASS* dlink_prev_##LISTNAME() const { return m_dlink_##LISTNAME.m_prev; } \
|
||||
OBJCLASS* dlink_next_##LISTNAME() const { return m_dlink_##LISTNAME.m_next; } \
|
||||
void dlink_swapLinks_##LISTNAME() \
|
||||
{ \
|
||||
OBJCLASS* originalNext = m_dlink_##LISTNAME.m_next; \
|
||||
m_dlink_##LISTNAME.m_next = m_dlink_##LISTNAME.m_prev; \
|
||||
m_dlink_##LISTNAME.m_prev = originalNext; \
|
||||
} \
|
||||
Bool dlink_isInList_##LISTNAME(OBJCLASS* const* pListHead) const \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
|
||||
return *pListHead == this || m_dlink_##LISTNAME.m_prev || m_dlink_##LISTNAME.m_next; \
|
||||
} \
|
||||
void dlink_prependTo_##LISTNAME(OBJCLASS** pListHead) \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(!dlink_isInList_##LISTNAME(pListHead), ("already in list " #LISTNAME)); \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
|
||||
m_dlink_##LISTNAME.m_next = *pListHead; \
|
||||
if (*pListHead) \
|
||||
(*pListHead)->m_dlink_##LISTNAME.m_prev = this; \
|
||||
*pListHead = this; \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
|
||||
} \
|
||||
void dlink_removeFrom_##LISTNAME(OBJCLASS** pListHead) \
|
||||
{ \
|
||||
DEBUG_ASSERTCRASH(dlink_isInList_##LISTNAME(pListHead), ("not in list" #LISTNAME)); \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
|
||||
if (m_dlink_##LISTNAME.m_next) \
|
||||
m_dlink_##LISTNAME.m_next->m_dlink_##LISTNAME.m_prev = m_dlink_##LISTNAME.m_prev; \
|
||||
if (m_dlink_##LISTNAME.m_prev) \
|
||||
m_dlink_##LISTNAME.m_prev->m_dlink_##LISTNAME.m_next = m_dlink_##LISTNAME.m_next; \
|
||||
else \
|
||||
*pListHead = m_dlink_##LISTNAME.m_next; \
|
||||
m_dlink_##LISTNAME.m_prev = 0; \
|
||||
m_dlink_##LISTNAME.m_next = 0; \
|
||||
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
|
||||
} \
|
||||
private: \
|
||||
/* a trick: init links to zero */ \
|
||||
struct DLINK_##LISTNAME \
|
||||
{ \
|
||||
public: \
|
||||
OBJCLASS* m_prev; \
|
||||
OBJCLASS* m_next; \
|
||||
inline DLINK_##LISTNAME() : \
|
||||
m_prev(0), m_next(0) { } \
|
||||
inline ~DLINK_##LISTNAME() \
|
||||
{ DEBUG_ASSERTCRASH(!m_prev && !m_next,("destroying dlink still in a list " #LISTNAME)); } \
|
||||
}; \
|
||||
DLINK_##LISTNAME m_dlink_##LISTNAME;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// this is the weird C++ syntax for "call pointer-to-member-function"... see C++ FAQ LITE for details.
|
||||
#define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember))
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
template<class OBJCLASS>
|
||||
class DLINK_ITERATOR
|
||||
{
|
||||
public:
|
||||
// this is the weird C++ syntax for "pointer-to-member-function"
|
||||
typedef OBJCLASS* (OBJCLASS::*GetNextFunc)() const;
|
||||
private:
|
||||
OBJCLASS* m_cur;
|
||||
GetNextFunc m_getNextFunc; // this is the weird C++ syntax for "pointer-to-member-function"
|
||||
public:
|
||||
DLINK_ITERATOR(OBJCLASS* cur, GetNextFunc getNextFunc) : m_cur(cur), m_getNextFunc(getNextFunc)
|
||||
{
|
||||
}
|
||||
|
||||
void advance()
|
||||
{
|
||||
if (m_cur)
|
||||
m_cur = callMemberFunction(*m_cur, m_getNextFunc)();
|
||||
}
|
||||
|
||||
Bool done() const
|
||||
{
|
||||
return m_cur == NULL;
|
||||
}
|
||||
|
||||
OBJCLASS* cur() const
|
||||
{
|
||||
return m_cur;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
enum WhichTurretType
|
||||
{
|
||||
TURRET_INVALID = -1,
|
||||
|
||||
TURRET_MAIN = 0,
|
||||
TURRET_ALT,
|
||||
|
||||
MAX_TURRETS
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// this normalizes an angle to the range -PI...PI.
|
||||
extern Real normalizeAngle(Real angle);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// this returns the difference between a1 and a2, normalized.
|
||||
inline Real stdAngleDiff(Real a1, Real a2)
|
||||
{
|
||||
return normalizeAngle(a1 - a2);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// NOTE NOTE NOTE: Keep TheRelationShipNames in sync with this enum
|
||||
enum Relationship
|
||||
{
|
||||
ENEMIES = 0,
|
||||
NEUTRAL,
|
||||
ALLIES
|
||||
};
|
||||
|
||||
|
||||
// TheRelationShipNames is defined in Common/GameCommon.cpp
|
||||
extern const char *TheRelationshipNames[];
|
||||
|
||||
#endif // _GAMECOMMON_H_
|
||||
|
Reference in a new issue