qzdoom/src/info.h
2006-05-06 03:25:12 +00:00

427 lines
11 KiB
C++

/*
** info.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2005 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
** Important restrictions because of the way FState is structured:
**
** The range of Frame is [0,63]. Since sprite naming conventions
** are even more restrictive than this, this isn't something to
** really worry about.
**
** The range of Tics is [-1,65534]. If Misc1 is important, then
** the range of Tics is reduced to [-1,254], because Misc1 also
** doubles as the high byte of the tic.
**
** The range of Misc1 is [-128,127] and Misc2's range is [0,255].
**
** When compiled with Visual C++, this struct is 16 bytes. With
** any other compiler (assuming a 32-bit architecture), it is 20 bytes.
** This is because with VC++, I can use the charizing operator to
** initialize the name array to exactly 4 chars. If GCC would
** compile something like char t = "PLYR"[0]; as char t = 'P'; then GCC
** could also use the 16-byte version. Unfortunately, GCC compiles it
** more like:
**
** char t;
** void initializer () {
** static const char str[]="PLYR";
** t = str[0];
** }
**
** While this does allow the use of a 16-byte FState, the additional
** code amounts to more than 4 bytes.
**
** If C++ would allow char name[4] = "PLYR"; without an error (as C does),
** I could just initialize the name as a regular string and be done with it.
*/
#ifndef __INFO_H__
#define __INFO_H__
#include <stddef.h>
#if !defined(_WIN32)
#include <inttypes.h> // for intptr_t
#elif !defined(_MSC_VER)
#include <stdint.h> // for mingw
#endif
#include "dobject.h"
#include "dthinker.h"
#include "farchive.h"
#include "doomdef.h"
#include "name.h"
const BYTE SF_STATEPARAM = 0x20;
const BYTE SF_FULLBRIGHT = 0x40;
const BYTE SF_BIGTIC = 0x80;
// All state parameters are stored in this array now.
// The first 2 parameters for each function call represent
// the old misc1/misc2 values, even for non-weapons
extern TArray<intptr_t> StateParameters;
struct FState
{
union
{
#if _MSC_VER
char name[4];
#else
char name[8]; // 4 for name, 1 for '\0', 3 for pad
#endif
int index;
} sprite;
BYTE Tics;
SBYTE Misc1;
BYTE Misc2;
BYTE Frame;
actionf_p Action;
FState *NextState;
inline int GetFrame() const
{
return Frame & ~(SF_FULLBRIGHT|SF_BIGTIC|SF_STATEPARAM);
}
inline int GetFullbright() const
{
return Frame & SF_FULLBRIGHT ? 0x10 /*RF_FULLBRIGHT*/ : 0;
}
inline int GetTics() const
{
int tics;
#ifdef WORDS_BIGENDIAN
tics = Frame & SF_BIGTIC ? (Tics|((BYTE)Misc1<<8))-1 : Tics-1;
#else
// Use some trickery to help the compiler create this without
// using any jumps.
tics = ((*(SDWORD *)&Tics) & ((*(SDWORD *)&Tics) < 0 ? 0xffff : 0xff)) - 1;
#endif
#if TICRATE == 35
return tics;
#else
return tics > 0 ? tics * TICRATE / 35 : tics;
#endif
}
inline int GetMisc1() const
{
return Frame & SF_BIGTIC ? 0 : Misc1;
}
inline int GetMisc2() const
{
return Misc2;
}
inline int GetMisc1_2() const
{
return ((*(DWORD *)&Tics) >> 8) & 0xFFFF;
}
inline void SetMisc1_2 (WORD val)
{
DWORD x = *(DWORD *)&Tics;
x &= 0xFF0000FF;
x |= (DWORD)val << 8;
*(DWORD *)&Tics = x;
}
inline FState *GetNextState() const
{
return NextState;
}
inline actionf_p GetAction() const
{
return Action;
}
inline void SetFrame(BYTE frame)
{
Frame = (Frame & (SF_FULLBRIGHT|SF_BIGTIC)) | (frame-'A');
}
static const TypeInfo *StaticFindStateOwner (const FState *state);
static const TypeInfo *StaticFindStateOwner (const FState *state, const FActorInfo *info);
};
// A truly awful hack to get to the state that called an action function
// without knowing whether it has been called from a weapon or actor.
extern FState * CallingState;
int CheckIndex(int paramsize, FState ** pcallstate=NULL);
FArchive &operator<< (FArchive &arc, FState *&state);
#if _MSC_VER
#define _S__SPRITE_(spr) \
{ {{(char)(#@spr>>24),(char)(#@spr>>16),(char)(#@spr>>8),(char)#@spr}}
#else
#define _S__SPRITE_(spr) \
{ {{#spr}}
#endif
#define _S__FR_TIC_(spr,frm,tic,m1,m2,cmd,next) \
_S__SPRITE_(spr), (tic+1)&255, m1|((tic+1)>>8), m2, (tic>254)?SF_BIGTIC|(frm):(frm), cmd, next }
#define S_NORMAL2(spr,frm,tic,cmd,next,m1,m2) \
_S__FR_TIC_(spr, (frm) - 'A', tic, m1, m2, cmd, next)
#define S_BRIGHT2(spr,frm,tic,cmd,next,m1,m2) \
_S__FR_TIC_(spr, (frm) - 'A' | SF_FULLBRIGHT, tic, m1, m2, cmd, next)
/* <winbase.h> #defines its own, completely unrelated S_NORMAL.
* Since winbase.h will only be included in Win32-specific files that
* don't define any actors, we can safely avoid defining it here.
*/
#ifndef S_NORMAL
#define S_NORMAL(spr,frm,tic,cmd,next) S_NORMAL2(spr,frm,tic,cmd,next,0,0)
#endif
#define S_BRIGHT(spr,frm,tic,cmd,next) S_BRIGHT2(spr,frm,tic,cmd,next,0,0)
#ifndef EGAMETYPE
#define EGAMETYPE
enum EGameType
{
GAME_Any = 0,
GAME_Doom = 1,
GAME_Heretic = 2,
GAME_Hexen = 4,
GAME_Strife = 8,
GAME_Raven = GAME_Heretic|GAME_Hexen,
GAME_DoomStrife = GAME_Doom|GAME_Strife
};
#endif
enum
{
ADEFTYPE_Byte = 0x0000,
ADEFTYPE_FixedMul = 0x4000, // one byte, multiplied by FRACUNIT
ADEFTYPE_Word = 0x8000,
ADEFTYPE_Long = 0xC000,
ADEFTYPE_MASK = 0xC000,
// These first properties are always strings
ADEF_SeeSound = 1,
ADEF_AttackSound,
ADEF_PainSound,
ADEF_DeathSound,
ADEF_ActiveSound,
ADEF_UseSound,
ADEF_Weapon_UpSound,
ADEF_Weapon_ReadySound,
ADEF_Inventory_PickupSound,
ADEF_Tag, // Used by Strife to name items
ADEF_Weapon_AmmoType1,
ADEF_Weapon_AmmoType2,
ADEF_Weapon_SisterType,
ADEF_Weapon_ProjectileType,
ADEF_PowerupGiver_Powerup,
ADEF_Inventory_Icon,
ADEF_LastString = ADEF_Inventory_Icon,
// The rest of the properties use their type field (upper 2 bits)
ADEF_XScale,
ADEF_YScale,
ADEF_SpawnHealth,
ADEF_ReactionTime,
ADEF_PainChance,
ADEF_Speed,
ADEF_Radius,
ADEF_Height,
ADEF_Mass,
ADEF_Damage,
ADEF_DamageType,
ADEF_Flags, // Use these flags exactly
ADEF_Flags2, // "
ADEF_Flags3, // "
ADEF_Flags4, // "
ADEF_Flags5, // "
ADEF_FlagsSet, // Or these flags with previous
ADEF_Flags2Set, // "
ADEF_Flags3Set, // "
ADEF_Flags4Set, // "
ADEF_Flags5Set, // "
ADEF_FlagsClear, // Clear these flags from previous
ADEF_Flags2Clear, // "
ADEF_Flags3Clear, // "
ADEF_Flags4Clear, // "
ADEF_Flags5Clear, // "
ADEF_Alpha,
ADEF_RenderStyle,
ADEF_RenderFlags,
ADEF_Translation,
ADEF_MinMissileChance,
ADEF_MeleeRange,
ADEF_MaxDropOffHeight,
ADEF_MaxStepHeight,
ADEF_BounceFactor,
ADEF_BounceCount,
ADEF_SpawnState,
ADEF_SeeState,
ADEF_PainState,
ADEF_MeleeState,
ADEF_MissileState,
ADEF_CrashState,
ADEF_DeathState,
ADEF_XDeathState,
ADEF_BDeathState,
ADEF_IDeathState,
ADEF_EDeathState,
ADEF_RaiseState,
ADEF_WoundState,
ADEF_YesState,
ADEF_NoState,
ADEF_GreetingsState,
ADEF_StrifeType, // Not really a property. Used to init StrifeTypes[] in p_conversation.h.
ADEF_StrifeTeaserType,
ADEF_StrifeTeaserType2,
ADEF_Inventory_Amount,
ADEF_Inventory_MaxAmount,
ADEF_Inventory_DefMaxAmount,
ADEF_Inventory_RespawnTics,
ADEF_Inventory_FlagsSet,
ADEF_Inventory_FlagsClear,
ADEF_PuzzleItem_Number, // Identifies the puzzle item for UsePuzzleItem
ADEF_BasicArmorPickup_SavePercent,
ADEF_BasicArmorPickup_SaveAmount,
ADEF_BasicArmorBonus_SavePercent,
ADEF_BasicArmorBonus_SaveAmount,
ADEF_BasicArmorBonus_MaxSaveAmount,
ADEF_HexenArmor_ArmorAmount,
ADEF_Powerup_EffectTics,
ADEF_Powerup_Color,
ADEF_PowerupGiver_EffectTics,
ADEF_Ammo_BackpackAmount,
ADEF_Ammo_BackpackMaxAmount,
ADEF_Weapon_Flags,
ADEF_Weapon_FlagsSet,
ADEF_Weapon_AmmoGive1,
ADEF_Weapon_AmmoGive2,
ADEF_Weapon_AmmoUse1,
ADEF_Weapon_AmmoUse2,
ADEF_Weapon_Kickback,
ADEF_Weapon_YAdjust,
ADEF_Weapon_SelectionOrder,
ADEF_Weapon_MoveCombatDist,
ADEF_Weapon_UpState,
ADEF_Weapon_DownState,
ADEF_Weapon_ReadyState,
ADEF_Weapon_AtkState,
ADEF_Weapon_HoldAtkState,
ADEF_Weapon_AltAtkState,
ADEF_Weapon_AltHoldAtkState,
ADEF_Weapon_FlashState,
ADEF_Sigil_NumPieces,
// The following are not properties but affect how the list is parsed
ADEF_FirstCommand,
ADEF_SkipSuper = ADEF_FirstCommand, // Take defaults from AActor instead of superclass(es)
ADEF_EOL = 0xED5E // End Of List
};
struct FStateName
{
FState *AActor::*State;
FName Name;
};
#if _MSC_VER
// nonstandard extension used : zero-sized array in struct/union
#pragma warning(disable:4200)
#endif
struct FActorInfo
{
static void StaticInit ();
static void StaticGameSet ();
static void StaticSetActorNums ();
static void StaticSpeedSet ();
void BuildDefaults ();
void ApplyDefaults (BYTE *defaults);
void RegisterIDs ();
TypeInfo *Class;
FState *OwnedStates;
BYTE *Defaults;
FStateName *StateNames;
int NumOwnedStates;
BYTE GameFilter;
BYTE SpawnID;
SWORD DoomEdNum;
#if _MSC_VER
// A 0-terminated list of default properties
BYTE DefaultList[];
#else
// A function to initialize the defaults for this actor
void (*DefaultsConstructor)();
#endif
};
#if _MSC_VER
#pragma warning(default:4200)
#endif
class FDoomEdMap
{
public:
const TypeInfo *FindType (int doomednum) const;
void AddType (int doomednum, const TypeInfo *type);
void DelType (int doomednum);
void Empty ();
static void DumpMapThings ();
private:
enum { DOOMED_HASHSIZE = 256 };
struct FDoomEdEntry
{
FDoomEdEntry *HashNext;
const TypeInfo *Type;
int DoomEdNum;
};
static FDoomEdEntry *DoomEdHash[DOOMED_HASHSIZE];
};
extern FDoomEdMap DoomEdMap;
#include "infomacros.h"
#endif // __INFO_H__