mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-01 16:41:09 +00:00
711471e9dd
https://forum.zdoom.org/viewtopic.php?t=57116 The problem was caused by missing state label in conjunction with incomplete class actor A : ArmorBonus { Inventory.ForbiddenTo "Missing" } actor B : Pistol { states { TNT1 A 0 Loop } }
446 lines
10 KiB
C++
446 lines
10 KiB
C++
/*
|
|
** info.h
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright 1998-2007 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.
|
|
**---------------------------------------------------------------------------
|
|
**
|
|
*/
|
|
|
|
#ifndef __INFO_H__
|
|
#define __INFO_H__
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include "dobject.h"
|
|
#include "doomdef.h"
|
|
#include "s_sound.h"
|
|
|
|
#include "m_fixed.h"
|
|
#include "m_random.h"
|
|
|
|
struct Baggage;
|
|
class FScanner;
|
|
struct FActorInfo;
|
|
class FIntCVar;
|
|
class FStateDefinitions;
|
|
class FInternalLightAssociation;
|
|
|
|
enum EStateDefineFlags
|
|
{
|
|
SDF_NEXT = 0,
|
|
SDF_STATE = 1,
|
|
SDF_STOP = 2,
|
|
SDF_WAIT = 3,
|
|
SDF_LABEL = 4,
|
|
SDF_INDEX = 5,
|
|
SDF_MASK = 7,
|
|
};
|
|
|
|
enum EStateFlags
|
|
{
|
|
STF_SLOW = 1, // State duration is extended when slow monsters is on.
|
|
STF_FAST = 2, // State duration is shortened when fast monsters is on.
|
|
STF_FULLBRIGHT = 4, // State is fullbright
|
|
STF_NODELAY = 8, // Spawn states executes its action normally
|
|
STF_SAMEFRAME = 16, // Ignore Frame (except when spawning actor)
|
|
STF_CANRAISE = 32, // Allows a monster to be resurrected without waiting for an infinate frame
|
|
STF_DEHACKED = 64, // Modified by Dehacked
|
|
};
|
|
|
|
enum EStateUseFlags
|
|
{
|
|
SUF_ACTOR = 1,
|
|
SUF_OVERLAY = 2,
|
|
SUF_WEAPON = 4,
|
|
SUF_ITEM = 8,
|
|
};
|
|
|
|
enum EStateType : int // this must ensure proper alignment.
|
|
{
|
|
STATE_Actor,
|
|
STATE_Psprite,
|
|
STATE_StateChain,
|
|
};
|
|
|
|
struct FStateParamInfo
|
|
{
|
|
FState *mCallingState;
|
|
EStateType mStateType;
|
|
int mPSPIndex;
|
|
};
|
|
|
|
|
|
// Sprites that are fixed in position because they can have special meanings.
|
|
enum
|
|
{
|
|
SPR_TNT1, // The empty sprite
|
|
SPR_FIXED, // Do not change sprite or frame
|
|
SPR_NOCHANGE, // Do not change sprite (frame change is okay)
|
|
};
|
|
|
|
struct FState
|
|
{
|
|
FState *NextState;
|
|
VMFunction *ActionFunc;
|
|
int32_t sprite;
|
|
int16_t Tics;
|
|
uint16_t TicRange;
|
|
int16_t Light;
|
|
uint16_t StateFlags;
|
|
uint8_t Frame;
|
|
uint8_t UseFlags;
|
|
uint8_t DefineFlags;
|
|
int32_t Misc1; // Was changed to int8_t, reverted to long for MBF compat
|
|
int32_t Misc2; // Was changed to uint8_t, reverted to long for MBF compat
|
|
public:
|
|
inline int GetFrame() const
|
|
{
|
|
return Frame;
|
|
}
|
|
inline bool GetSameFrame() const
|
|
{
|
|
return !!(StateFlags & STF_SAMEFRAME);
|
|
}
|
|
inline int GetFullbright() const
|
|
{
|
|
return (StateFlags & STF_FULLBRIGHT)? 0x10 /*RF_FULLBRIGHT*/ : 0;
|
|
}
|
|
inline bool GetFast() const
|
|
{
|
|
return !!(StateFlags & STF_FAST);
|
|
}
|
|
inline bool GetSlow() const
|
|
{
|
|
return !!(StateFlags & STF_SLOW);
|
|
}
|
|
inline bool GetNoDelay() const
|
|
{
|
|
return !!(StateFlags & STF_NODELAY);
|
|
}
|
|
inline bool GetCanRaise() const
|
|
{
|
|
return !!(StateFlags & STF_CANRAISE);
|
|
}
|
|
inline int GetTics() const
|
|
{
|
|
if (TicRange == 0)
|
|
{
|
|
return Tics;
|
|
}
|
|
return Tics + pr_statetics.GenRand32() % (TicRange + 1);
|
|
}
|
|
inline int GetMisc1() const
|
|
{
|
|
return Misc1;
|
|
}
|
|
inline int GetMisc2() const
|
|
{
|
|
return Misc2;
|
|
}
|
|
inline FState *GetNextState() const
|
|
{
|
|
return NextState;
|
|
}
|
|
inline void SetFrame(uint8_t frame)
|
|
{
|
|
Frame = frame - 'A';
|
|
}
|
|
void SetAction(VMFunction *func) { ActionFunc = func; }
|
|
void ClearAction() { ActionFunc = NULL; }
|
|
void SetAction(const char *name);
|
|
bool CallAction(AActor *self, AActor *stateowner, FStateParamInfo *stateinfo, FState **stateret);
|
|
static PClassActor *StaticFindStateOwner (const FState *state);
|
|
static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info);
|
|
static FString StaticGetStateName(const FState *state);
|
|
static FRandom pr_statetics;
|
|
};
|
|
|
|
struct FStateLabels;
|
|
struct FStateLabel
|
|
{
|
|
FName Label;
|
|
FState *State;
|
|
FStateLabels *Children;
|
|
};
|
|
|
|
struct FStateLabels
|
|
{
|
|
int NumLabels;
|
|
FStateLabel Labels[1];
|
|
|
|
FStateLabel *FindLabel (FName label);
|
|
|
|
void Destroy(); // intentionally not a destructor!
|
|
};
|
|
|
|
#include "gametype.h"
|
|
|
|
struct DmgFactors : public TArray<std::pair<FName, double>>
|
|
{
|
|
int Apply(FName type, int damage);
|
|
};
|
|
typedef TArray<std::pair<FName, int>> PainChanceList;
|
|
|
|
struct DamageTypeDefinition
|
|
{
|
|
public:
|
|
DamageTypeDefinition() { Clear(); }
|
|
|
|
FString Obituary;
|
|
double DefaultFactor;
|
|
bool ReplaceFactor;
|
|
bool NoArmor;
|
|
|
|
void Apply(FName type);
|
|
void Clear()
|
|
{
|
|
Obituary = "";
|
|
DefaultFactor = 1.;
|
|
ReplaceFactor = false;
|
|
NoArmor = false;
|
|
}
|
|
|
|
static bool IgnoreArmor(FName type);
|
|
static int ApplyMobjDamageFactor(int damage, FName type, DmgFactors const * const factors);
|
|
static FString GetObituary(FName type);
|
|
|
|
private:
|
|
static double GetMobjDamageFactor(FName type, DmgFactors const * const factors);
|
|
static DamageTypeDefinition *Get(FName type);
|
|
};
|
|
|
|
struct FDropItem;
|
|
|
|
struct FActorInfo
|
|
{
|
|
TArray<FInternalLightAssociation *> LightAssociations;
|
|
PClassActor *Replacement = nullptr;
|
|
PClassActor *Replacee = nullptr;
|
|
FState *OwnedStates = nullptr;
|
|
int NumOwnedStates = 0;
|
|
bool SkipSuperSet = false;
|
|
uint8_t GameFilter = GAME_Any;
|
|
uint16_t SpawnID = 0;
|
|
uint16_t ConversationID = 0;
|
|
int16_t DoomEdNum = -1;
|
|
|
|
FStateLabels *StateList = nullptr;
|
|
DmgFactors DamageFactors;
|
|
PainChanceList PainChances;
|
|
|
|
TArray<PClassActor *> VisibleToPlayerClass;
|
|
|
|
FDropItem *DropItems;
|
|
FIntCVar *distancecheck;
|
|
|
|
// This is from PClassPlayerPawn
|
|
FString DisplayName;
|
|
|
|
uint8_t DefaultStateUsage = 0; // state flag defaults for blocks without a qualifier.
|
|
|
|
FActorInfo() {}
|
|
FActorInfo(const FActorInfo & other)
|
|
{
|
|
// only copy the fields that get inherited
|
|
DefaultStateUsage = other.DefaultStateUsage;
|
|
DamageFactors = other.DamageFactors;
|
|
PainChances = other.PainChances;
|
|
VisibleToPlayerClass = other.VisibleToPlayerClass;
|
|
DropItems = other.DropItems;
|
|
distancecheck = other.distancecheck;
|
|
DisplayName = other.DisplayName;
|
|
}
|
|
|
|
~FActorInfo()
|
|
{
|
|
if (StateList != NULL)
|
|
{
|
|
StateList->Destroy();
|
|
M_Free(StateList);
|
|
}
|
|
}
|
|
};
|
|
|
|
// This is now merely a wrapper that adds actor-specific functionality to PClass.
|
|
// No objects of this type will be created ever - its only use is to static_cast
|
|
// PClass to it.
|
|
class PClassActor : public PClass
|
|
{
|
|
protected:
|
|
public:
|
|
static void StaticInit ();
|
|
static void StaticSetActorNums ();
|
|
|
|
void BuildDefaults();
|
|
void ApplyDefaults(uint8_t *defaults);
|
|
void RegisterIDs();
|
|
void SetDamageFactor(FName type, double factor);
|
|
void SetPainChance(FName type, int chance);
|
|
bool SetReplacement(FName replaceName);
|
|
|
|
FActorInfo *ActorInfo() const
|
|
{
|
|
return (FActorInfo*)Meta;
|
|
}
|
|
|
|
void SetDropItems(FDropItem *drops)
|
|
{
|
|
ActorInfo()->DropItems = drops;
|
|
}
|
|
|
|
const FString &GetDisplayName() const
|
|
{
|
|
return ActorInfo()->DisplayName;
|
|
}
|
|
|
|
FState *GetStates() const
|
|
{
|
|
return ActorInfo()->OwnedStates;
|
|
}
|
|
|
|
unsigned GetStateCount() const
|
|
{
|
|
return ActorInfo()->NumOwnedStates;
|
|
}
|
|
|
|
FStateLabels *GetStateLabels() const
|
|
{
|
|
return ActorInfo()->StateList;
|
|
}
|
|
|
|
FState *FindState(int numnames, FName *names, bool exact=false) const;
|
|
FState *FindStateByString(const char *name, bool exact=false);
|
|
FState *FindState(FName name) const
|
|
{
|
|
return FindState(1, &name);
|
|
}
|
|
|
|
bool OwnsState(const FState *state)
|
|
{
|
|
auto i = ActorInfo();
|
|
return i != nullptr && state >= i->OwnedStates && state < i->OwnedStates + i->NumOwnedStates;
|
|
}
|
|
|
|
PClassActor *GetReplacement(bool lookskill=true);
|
|
PClassActor *GetReplacee(bool lookskill=true);
|
|
|
|
// For those times when being able to scan every kind of actor is convenient
|
|
static TArray<PClassActor *> AllActorClasses;
|
|
};
|
|
|
|
struct FDoomEdEntry
|
|
{
|
|
PClassActor *Type;
|
|
short Special;
|
|
signed char ArgsDefined;
|
|
bool NoSkillFlags;
|
|
int Args[5];
|
|
};
|
|
|
|
struct FStateLabelStorage
|
|
{
|
|
TArray<uint8_t> Storage;
|
|
|
|
int AddPointer(FState *ptr)
|
|
{
|
|
if (ptr != nullptr)
|
|
{
|
|
int pos = Storage.Reserve(sizeof(ptr) + sizeof(int));
|
|
memset(&Storage[pos], 0, sizeof(int));
|
|
memcpy(&Storage[pos + sizeof(int)], &ptr, sizeof(ptr));
|
|
return pos / 4 + 1;
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
int AddNames(TArray<FName> &names)
|
|
{
|
|
int siz = names.Size();
|
|
if (siz > 1)
|
|
{
|
|
int pos = Storage.Reserve(sizeof(int) + sizeof(FName) * names.Size());
|
|
memcpy(&Storage[pos], &siz, sizeof(int));
|
|
memcpy(&Storage[pos + sizeof(int)], &names[0], sizeof(FName) * names.Size());
|
|
return pos / 4 + 1;
|
|
}
|
|
else
|
|
{
|
|
// don't store single name states in the array.
|
|
return names[0].GetIndex() + 0x10000000;
|
|
}
|
|
}
|
|
|
|
FState *GetState(int pos, PClassActor *cls, bool exact = false);
|
|
};
|
|
|
|
extern FStateLabelStorage StateLabels;
|
|
|
|
enum ESpecialMapthings
|
|
{
|
|
SMT_Player1Start = 1,
|
|
SMT_Player2Start,
|
|
SMT_Player3Start,
|
|
SMT_Player4Start,
|
|
SMT_Player5Start,
|
|
SMT_Player6Start,
|
|
SMT_Player7Start,
|
|
SMT_Player8Start,
|
|
SMT_DeathmatchStart,
|
|
SMT_SSeqOverride,
|
|
SMT_PolyAnchor,
|
|
SMT_PolySpawn,
|
|
SMT_PolySpawnCrush,
|
|
SMT_PolySpawnHurt,
|
|
SMT_SlopeFloorPointLine,
|
|
SMT_SlopeCeilingPointLine,
|
|
SMT_SetFloorSlope,
|
|
SMT_SetCeilingSlope,
|
|
SMT_VavoomFloor,
|
|
SMT_VavoomCeiling,
|
|
SMT_CopyFloorPlane,
|
|
SMT_CopyCeilingPlane,
|
|
SMT_VertexFloorZ,
|
|
SMT_VertexCeilingZ,
|
|
SMT_EDThing,
|
|
|
|
};
|
|
|
|
|
|
typedef TMap<int, FDoomEdEntry> FDoomEdMap;
|
|
|
|
extern FDoomEdMap DoomEdMap;
|
|
|
|
void InitActorNumsFromMapinfo();
|
|
|
|
|
|
int GetSpriteIndex(const char * spritename, bool add = true);
|
|
TArray<FName> &MakeStateNameList(const char * fname);
|
|
void AddStateLight(FState *state, const char *lname);
|
|
|
|
#endif // __INFO_H__
|