mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-23 20:42:24 +00:00
Re-allow indexes as state parameter in sequences
This commit is contained in:
parent
a4142ad9fb
commit
db9f4c1385
4 changed files with 120 additions and 11 deletions
|
@ -654,6 +654,7 @@ xx(DecoCallLineSpecial)
|
||||||
xx(DecoNameToClass)
|
xx(DecoNameToClass)
|
||||||
xx(DecoFindMultiNameState)
|
xx(DecoFindMultiNameState)
|
||||||
xx(DecoFindSingleNameState)
|
xx(DecoFindSingleNameState)
|
||||||
|
xx(DecoHandleRuntimeState)
|
||||||
xx(Damage)
|
xx(Damage)
|
||||||
|
|
||||||
// basic type names
|
// basic type names
|
||||||
|
|
|
@ -1058,6 +1058,24 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Same as above except for expressions which means it will have to be
|
||||||
|
// evaluated at runtime
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxRuntimeStateIndex : public FxExpression
|
||||||
|
{
|
||||||
|
FxExpression *Index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FxRuntimeStateIndex(FxExpression *index);
|
||||||
|
~FxRuntimeStateIndex();
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -4428,7 +4428,90 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FxRuntimeStateIndex::FxRuntimeStateIndex(FxExpression *index)
|
||||||
|
: FxExpression(index->ScriptPosition), Index(index)
|
||||||
|
{
|
||||||
|
ValueType = TypeState;
|
||||||
|
}
|
||||||
|
|
||||||
|
FxRuntimeStateIndex::~FxRuntimeStateIndex()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx)
|
||||||
|
{
|
||||||
|
CHECKRESOLVED();
|
||||||
|
SAFE_RESOLVE(Index, ctx);
|
||||||
|
|
||||||
|
if (!Index->IsNumeric())
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else if (Index->ValueType->GetRegType() != REGT_INT)
|
||||||
|
{ // Float.
|
||||||
|
Index = new FxIntCast(Index);
|
||||||
|
SAFE_RESOLVE(Index, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_OBJECT(stateowner, AActor);
|
||||||
|
PARAM_POINTER(stateinfo, FStateParamInfo);
|
||||||
|
PARAM_INT(index);
|
||||||
|
|
||||||
|
if (index == 0 || !stateowner->GetClass()->OwnsState(stateinfo->mCallingState + index))
|
||||||
|
{
|
||||||
|
// Null is returned if the location was invalid which means that no jump will be performed
|
||||||
|
// if used as return value
|
||||||
|
// 0 always meant the same thing so we handle it here for compatibility
|
||||||
|
ret->SetPointer(nullptr, ATAG_STATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret->SetPointer(stateinfo->mCallingState + index, ATAG_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
assert(build->Registers[REGT_POINTER].GetMostUsed() >= 3);
|
||||||
|
|
||||||
|
ExpEmit out(build, REGT_POINTER);
|
||||||
|
|
||||||
|
build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // stateowner
|
||||||
|
build->Emit(OP_PARAM, 0, REGT_POINTER, 2); // stateinfo
|
||||||
|
ExpEmit id = Index->Emit(build);
|
||||||
|
build->Emit(OP_PARAM, 0, REGT_INT | (id.Konst ? REGT_KONST : 0), id.RegNum); // index
|
||||||
|
|
||||||
|
VMFunction *callfunc;
|
||||||
|
PSymbol *sym;
|
||||||
|
|
||||||
|
sym = FindDecorateBuiltinFunction(NAME_DecoHandleRuntimeState, DecoHandleRuntimeState);
|
||||||
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1);
|
||||||
|
build->Emit(OP_RESULT, 0, REGT_POINTER, out.RegNum);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -138,23 +138,30 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
|
||||||
else if (type == TypeState)
|
else if (type == TypeState)
|
||||||
{
|
{
|
||||||
// This forces quotation marks around the state name.
|
// This forces quotation marks around the state name.
|
||||||
sc.MustGetToken(TK_StringConst);
|
if (sc.CheckToken(TK_StringConst))
|
||||||
if (sc.String[0] == 0 || sc.Compare("None"))
|
|
||||||
{
|
{
|
||||||
x = new FxConstant((FState*)NULL, sc);
|
if (sc.String[0] == 0 || sc.Compare("None"))
|
||||||
}
|
|
||||||
else if (sc.Compare("*"))
|
|
||||||
{
|
|
||||||
if (constant)
|
|
||||||
{
|
{
|
||||||
x = new FxConstant((FState*)(intptr_t)-1, sc);
|
x = new FxConstant((FState*)NULL, sc);
|
||||||
|
}
|
||||||
|
else if (sc.Compare("*"))
|
||||||
|
{
|
||||||
|
if (constant)
|
||||||
|
{
|
||||||
|
x = new FxConstant((FState*)(intptr_t)-1, sc);
|
||||||
|
}
|
||||||
|
else sc.ScriptError("Invalid state name '*'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = new FxMultiNameState(sc.String, sc);
|
||||||
}
|
}
|
||||||
else sc.ScriptError("Invalid state name '*'");
|
|
||||||
}
|
}
|
||||||
else
|
else if (!constant)
|
||||||
{
|
{
|
||||||
x = new FxMultiNameState(sc.String, sc);
|
x = new FxRuntimeStateIndex(ParseExpression(sc, cls));
|
||||||
}
|
}
|
||||||
|
else sc.MustGetToken(TK_StringConst); // This is for the error.
|
||||||
}
|
}
|
||||||
else if (type->GetClass() == RUNTIME_CLASS(PClassPointer))
|
else if (type->GetClass() == RUNTIME_CLASS(PClassPointer))
|
||||||
{ // Actor name
|
{ // Actor name
|
||||||
|
|
Loading…
Reference in a new issue