mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
- implemented State as an actual native struct, so that its fields can be accessed from scripts.
- refactored state bitfield members into a flag word because the address of a bitfield cannot be taken, making such variables inaccessible to scripts. - actually use PNativeStruct for representing native structs defined in a script.
This commit is contained in:
parent
ff3baac8a7
commit
135cfcf016
12 changed files with 102 additions and 65 deletions
|
@ -1466,28 +1466,21 @@ static int PatchFrame (int frameNum)
|
|||
|
||||
if (info != &dummy)
|
||||
{
|
||||
info->DefineFlags |= SDF_DEHACKED; // Signals the state has been modified by dehacked
|
||||
info->StateFlags |= STF_DEHACKED; // Signals the state has been modified by dehacked
|
||||
if ((unsigned)(frame & 0x7fff) > 63)
|
||||
{
|
||||
Printf ("Frame %d: Subnumber must be in range [0,63]\n", frameNum);
|
||||
Printf("Frame %d: Subnumber must be in range [0,63]\n", frameNum);
|
||||
}
|
||||
info->Tics = tics;
|
||||
info->Misc1 = misc1;
|
||||
info->Frame = frame & 0x3f;
|
||||
info->Fullbright = frame & 0x8000 ? true : false;
|
||||
if (frame & 0x8000) info->StateFlags |= STF_FULLBRIGHT;
|
||||
else info->StateFlags &= STF_FULLBRIGHT;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// there is exactly one place where this is needed and we do not want to expose the state internals to ZSCRIPT.
|
||||
DEFINE_ACTION_FUNCTION(AActor, isDEHState)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(state, FState);
|
||||
ACTION_RETURN_BOOL(state != nullptr && (state->DefineFlags & SDF_DEHACKED));
|
||||
}
|
||||
|
||||
static int PatchSprite (int sprNum)
|
||||
{
|
||||
int result;
|
||||
|
|
|
@ -558,6 +558,7 @@ void PType::StaticInit()
|
|||
RUNTIME_CLASS(PDynArray)->TypeTableType = RUNTIME_CLASS(PDynArray);
|
||||
RUNTIME_CLASS(PMap)->TypeTableType = RUNTIME_CLASS(PMap);
|
||||
RUNTIME_CLASS(PStruct)->TypeTableType = RUNTIME_CLASS(PStruct);
|
||||
RUNTIME_CLASS(PNativeStruct)->TypeTableType = RUNTIME_CLASS(PNativeStruct);
|
||||
RUNTIME_CLASS(PPrototype)->TypeTableType = RUNTIME_CLASS(PPrototype);
|
||||
RUNTIME_CLASS(PClass)->TypeTableType = RUNTIME_CLASS(PClass);
|
||||
RUNTIME_CLASS(PStatePointer)->TypeTableType = RUNTIME_CLASS(PStatePointer);
|
||||
|
@ -2469,7 +2470,7 @@ PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer)
|
|||
PType *stype = TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, &bucket);
|
||||
if (stype == NULL)
|
||||
{
|
||||
stype = new PStruct(name, outer);
|
||||
stype = new PNativeStruct(name);
|
||||
TypeTable.AddType(stype, RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, bucket);
|
||||
}
|
||||
return static_cast<PNativeStruct *>(stype);
|
||||
|
|
71
src/info.h
71
src/info.h
|
@ -63,7 +63,17 @@ enum EStateDefineFlags
|
|||
SDF_LABEL = 4,
|
||||
SDF_INDEX = 5,
|
||||
SDF_MASK = 7,
|
||||
SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -101,33 +111,44 @@ struct FState
|
|||
{
|
||||
FState *NextState;
|
||||
VMFunction *ActionFunc;
|
||||
WORD sprite;
|
||||
SWORD Tics;
|
||||
WORD TicRange;
|
||||
short Light;
|
||||
BYTE Frame;
|
||||
BYTE UseFlags;
|
||||
BYTE DefineFlags; // Unused byte so let's use it during state creation.
|
||||
int Misc1; // Was changed to SBYTE, reverted to long for MBF compat
|
||||
int Misc2; // Was changed to BYTE, reverted to long for MBF compat
|
||||
BYTE Fullbright:1; // State is fullbright
|
||||
BYTE SameFrame:1; // Ignore Frame (except when spawning actor)
|
||||
BYTE Fast:1;
|
||||
BYTE NoDelay:1; // Spawn states executes its action normally
|
||||
BYTE CanRaise:1; // Allows a monster to be resurrected without waiting for an infinate frame
|
||||
BYTE Slow:1; // Inverse of fast
|
||||
|
||||
int32_t sprite;
|
||||
int16_t Tics;
|
||||
uint16_t TicRange;
|
||||
int16_t Light;
|
||||
uint16_t StateFlags;
|
||||
uint8_t Frame;
|
||||
uint8_t UseFlags;
|
||||
uint8_t DefineFlags; // Unused byte so let's use it during state creation.
|
||||
int32_t Misc1; // Was changed to SBYTE, reverted to long for MBF compat
|
||||
int32_t Misc2; // Was changed to BYTE, reverted to long for MBF compat
|
||||
public:
|
||||
inline int GetFrame() const
|
||||
{
|
||||
return Frame;
|
||||
}
|
||||
inline bool GetSameFrame() const
|
||||
{
|
||||
return SameFrame;
|
||||
return !!(StateFlags & STF_SAMEFRAME);
|
||||
}
|
||||
inline int GetFullbright() const
|
||||
{
|
||||
return Fullbright ? 0x10 /*RF_FULLBRIGHT*/ : 0;
|
||||
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
|
||||
{
|
||||
|
@ -149,22 +170,10 @@ struct FState
|
|||
{
|
||||
return NextState;
|
||||
}
|
||||
inline bool GetNoDelay() const
|
||||
{
|
||||
return NoDelay;
|
||||
}
|
||||
inline bool GetCanRaise() const
|
||||
{
|
||||
return CanRaise;
|
||||
}
|
||||
inline void SetFrame(BYTE frame)
|
||||
{
|
||||
Frame = frame - 'A';
|
||||
}
|
||||
inline bool CheckUse(int usetype)
|
||||
{
|
||||
return !!(UseFlags & usetype);
|
||||
}
|
||||
void SetAction(VMFunction *func) { ActionFunc = func; }
|
||||
void ClearAction() { ActionFunc = NULL; }
|
||||
void SetAction(const char *name);
|
||||
|
|
|
@ -584,11 +584,11 @@ bool AActor::InStateSequence(FState * newstate, FState * basestate)
|
|||
int AActor::GetTics(FState * newstate)
|
||||
{
|
||||
int tics = newstate->GetTics();
|
||||
if (isFast() && newstate->Fast)
|
||||
if (isFast() && newstate->GetFast())
|
||||
{
|
||||
return tics - (tics>>1);
|
||||
}
|
||||
else if (isSlow() && newstate->Slow)
|
||||
else if (isSlow() && newstate->GetSlow())
|
||||
{
|
||||
return tics<<1;
|
||||
}
|
||||
|
|
|
@ -924,9 +924,9 @@ int FStateDefinitions::AddStates(FState *state, const char *framechars, const FS
|
|||
|
||||
if (*framechars == '#')
|
||||
noframe = true;
|
||||
else if (*framechars == '^')
|
||||
else if (*framechars == '^')
|
||||
frame = '\\' - 'A';
|
||||
else
|
||||
else
|
||||
frame = (*framechars & 223) - 'A';
|
||||
|
||||
framechars++;
|
||||
|
@ -937,13 +937,14 @@ int FStateDefinitions::AddStates(FState *state, const char *framechars, const FS
|
|||
}
|
||||
|
||||
state->Frame = frame;
|
||||
state->SameFrame = noframe;
|
||||
if (noframe) state->StateFlags |= STF_SAMEFRAME;
|
||||
else state->StateFlags &= STF_SAMEFRAME;
|
||||
StateArray.Push(*state);
|
||||
SourceLines.Push(sc);
|
||||
++count;
|
||||
|
||||
// NODELAY flag is not carried past the first state
|
||||
state->NoDelay = false;
|
||||
state->StateFlags &= STF_NODELAY;
|
||||
}
|
||||
laststate = &StateArray[StateArray.Size() - 1];
|
||||
laststatebeforelabel = laststate;
|
||||
|
@ -1055,3 +1056,31 @@ CCMD(dumpstates)
|
|||
Printf(PRINT_LOG, "----------------------------\n");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// sets up the script-side version of states
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void P_InitStateForScript()
|
||||
{
|
||||
PNativeStruct *pstruct = dyn_cast<PNativeStruct>(TypeState->PointedType);
|
||||
assert(pstruct != nullptr);
|
||||
|
||||
pstruct->AddNativeField("NextState", TypeState, myoffsetof(FState, NextState), VARF_ReadOnly);
|
||||
pstruct->AddNativeField("sprite", TypeSInt32, myoffsetof(FState, sprite), VARF_ReadOnly);
|
||||
pstruct->AddNativeField("Tics", TypeSInt16, myoffsetof(FState, Tics), VARF_ReadOnly);
|
||||
pstruct->AddNativeField("TicRange", TypeUInt16, myoffsetof(FState, TicRange), VARF_ReadOnly);
|
||||
pstruct->AddNativeField("Frame", TypeUInt8, myoffsetof(FState, Frame), VARF_ReadOnly);
|
||||
pstruct->AddNativeField("UseFlags", TypeUInt8, myoffsetof(FState, UseFlags), VARF_ReadOnly);
|
||||
pstruct->AddNativeField("Misc1", TypeSInt32, myoffsetof(FState, Misc1), VARF_ReadOnly);
|
||||
pstruct->AddNativeField("Misc2", TypeSInt32, myoffsetof(FState, Misc2), VARF_ReadOnly);
|
||||
pstruct->AddNativeField("bSlow", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_SLOW);
|
||||
pstruct->AddNativeField("bFast", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_FAST);
|
||||
pstruct->AddNativeField("bFullbright", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_FULLBRIGHT);
|
||||
pstruct->AddNativeField("bNoDelay", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_NODELAY);
|
||||
pstruct->AddNativeField("bSameFrame", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_SAMEFRAME);
|
||||
pstruct->AddNativeField("bCanRaise", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_CANRAISE);
|
||||
pstruct->AddNativeField("bDehacked", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_DEHACKED);
|
||||
}
|
|
@ -5679,7 +5679,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct)))
|
||||
else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
{
|
||||
auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PStruct *>(Object->ValueType));
|
||||
delete this;
|
||||
|
@ -6278,7 +6278,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (classx->ValueType->IsA(RUNTIME_CLASS(PStruct))) // Classes can never be used as value types so we do not have to consider that case.
|
||||
else if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
{
|
||||
// if this is a struct within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
|
||||
if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember)
|
||||
|
|
|
@ -699,7 +699,7 @@ static void ParseSpriteFrames (PClassActor *info, TArray<FState> &states, TArray
|
|||
{
|
||||
sc.ScriptError ("* must come after a frame");
|
||||
}
|
||||
state.Fullbright = true;
|
||||
state.StateFlags |= STF_FULLBRIGHT;
|
||||
}
|
||||
else if (*token < 'A' || *token > ']')
|
||||
{
|
||||
|
|
|
@ -274,24 +274,24 @@ do_stop:
|
|||
{
|
||||
if (sc.Compare("BRIGHT"))
|
||||
{
|
||||
state.Fullbright = true;
|
||||
state.StateFlags |= STF_FULLBRIGHT;
|
||||
continue;
|
||||
}
|
||||
if (sc.Compare("FAST"))
|
||||
{
|
||||
state.Fast = true;
|
||||
state.StateFlags |= STF_FAST;
|
||||
continue;
|
||||
}
|
||||
if (sc.Compare("SLOW"))
|
||||
{
|
||||
state.Slow = true;
|
||||
state.StateFlags |= STF_SLOW;
|
||||
continue;
|
||||
}
|
||||
if (sc.Compare("NODELAY"))
|
||||
{
|
||||
if (bag.statedef.GetStateLabelIndex(NAME_Spawn) == bag.statedef.GetStateCount())
|
||||
{
|
||||
state.NoDelay = true;
|
||||
state.StateFlags |= STF_NODELAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -327,7 +327,7 @@ do_stop:
|
|||
}
|
||||
if (sc.Compare("CANRAISE"))
|
||||
{
|
||||
state.CanRaise = true;
|
||||
state.StateFlags |= STF_CANRAISE;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -658,6 +658,7 @@ static int funccmp(const void * a, const void * b)
|
|||
//==========================================================================
|
||||
void G_InitLevelLocalsForScript();
|
||||
void P_InitPlayerForScript();
|
||||
void P_InitStateForScript();
|
||||
|
||||
void InitThingdef()
|
||||
{
|
||||
|
@ -669,6 +670,7 @@ void InitThingdef()
|
|||
|
||||
G_InitLevelLocalsForScript();
|
||||
P_InitPlayerForScript();
|
||||
P_InitStateForScript();
|
||||
|
||||
FAutoSegIterator probe(CRegHead, CRegTail);
|
||||
|
||||
|
|
|
@ -416,7 +416,10 @@ void ZCCCompiler::CreateStructTypes()
|
|||
for(auto s : Structs)
|
||||
{
|
||||
s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->CType();
|
||||
s->strct->Type = NewStruct(s->NodeName(), s->Outer);
|
||||
if (s->strct->Flags & ZCC_Native)
|
||||
s->strct->Type = NewNativeStruct(s->NodeName(), nullptr);
|
||||
else
|
||||
s->strct->Type = NewStruct(s->NodeName(), s->Outer);
|
||||
s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type());
|
||||
GlobalSymbols.AddSymbol(s->strct->Symbol);
|
||||
|
||||
|
@ -2568,11 +2571,12 @@ void ZCCCompiler::CompileStates()
|
|||
Error(sl, "Duration is not a constant");
|
||||
}
|
||||
}
|
||||
state.Fullbright = sl->bBright;
|
||||
state.Fast = sl->bFast;
|
||||
state.Slow = sl->bSlow;
|
||||
state.CanRaise = sl->bCanRaise;
|
||||
if ((state.NoDelay = sl->bNoDelay))
|
||||
if (sl->bBright) state.StateFlags |= STF_FULLBRIGHT;
|
||||
if (sl->bFast) state.StateFlags |= STF_FAST;
|
||||
if (sl->bSlow) state.StateFlags |= STF_SLOW;
|
||||
if (sl->bCanRaise) state.StateFlags |= STF_CANRAISE;
|
||||
if (sl->bNoDelay) state.StateFlags |= STF_NODELAY;
|
||||
if (sl->bNoDelay)
|
||||
{
|
||||
if (statedef.GetStateLabelIndex(NAME_Spawn) != statedef.GetStateCount())
|
||||
{
|
||||
|
|
|
@ -78,7 +78,6 @@ class Actor : Thinker native
|
|||
native bool GiveBody (int num, int max=0);
|
||||
|
||||
native void SetDamage(int dmg);
|
||||
native static bool isDehState(state st);
|
||||
native double Distance2D(Actor other);
|
||||
native void SetOrigin(vector3 newpos, bool moving);
|
||||
native void SetXYZ(vector3 newpos);
|
||||
|
|
|
@ -192,7 +192,7 @@ extend class Actor
|
|||
aimtarget.Height = Height;
|
||||
|
||||
bool shootmode = ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options
|
||||
(flags == 0 && isDehState(CurState) && compat_mushroom));
|
||||
(flags == 0 && CurState.bDehacked && compat_mushroom));
|
||||
|
||||
for (i = -numspawns; i <= numspawns; i += 8)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue