Make actor damages readable from DECORATE (again)

This commit is contained in:
Randy Heit 2015-01-10 23:02:00 -06:00
parent 9b81e0e597
commit bd3e49c0e8
3 changed files with 80 additions and 0 deletions

View file

@ -610,6 +610,7 @@ xx(DecoCallLineSpecial)
xx(DecoNameToClass) xx(DecoNameToClass)
xx(DecoFindMultiNameState) xx(DecoFindMultiNameState)
xx(DecoFindSingleNameState) xx(DecoFindSingleNameState)
xx(Damage)
// basic type names // basic type names
xx(Default) xx(Default)

View file

@ -719,6 +719,20 @@ public:
ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build);
}; };
//==========================================================================
//
// FxDamage
//
//==========================================================================
class FxDamage : public FxExpression
{
public:
FxDamage(const FScriptPosition&);
FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build);
};
//========================================================================== //==========================================================================
// //
// FxArrayElement // FxArrayElement

View file

@ -2424,6 +2424,11 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars());
} }
} }
// the damage property needs special handling
else if (Identifier == NAME_Damage)
{
newex = new FxDamage(ScriptPosition);
}
// now check the global identifiers. // now check the global identifiers.
else if ((sym = ctx.FindGlobal(Identifier)) != NULL) else if ((sym = ctx.FindGlobal(Identifier)) != NULL)
{ {
@ -2516,6 +2521,66 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
return me; return me;
} }
//==========================================================================
//
//
//
//==========================================================================
FxDamage::FxDamage(const FScriptPosition &pos)
: FxExpression(pos)
{
}
//==========================================================================
//
// FxDamage :: Resolve
//
//==========================================================================
FxExpression *FxDamage::Resolve(FCompileContext& ctx)
{
CHECKRESOLVED();
ValueType = VAL_Int;
return this;
}
//==========================================================================
//
// FxDamage :: Emit
//
// Call this actor's damage function, if it has one
//
//==========================================================================
ExpEmit FxDamage::Emit(VMFunctionBuilder *build)
{
ExpEmit dmgval(build, REGT_INT);
// Get damage function
ExpEmit dmgfunc(build, REGT_POINTER);
build->Emit(OP_LO, dmgfunc.RegNum, 0/*self*/, build->GetConstantInt(myoffsetof(AActor, Damage)));
// If it's non-null...
build->Emit(OP_EQA_K, 1, dmgfunc.RegNum, build->GetConstantAddress(0, ATAG_GENERIC));
size_t nulljump = build->Emit(OP_JMP, 0);
// ...call it
build->Emit(OP_PARAM, 0, REGT_POINTER, 0/*self*/);
build->Emit(OP_CALL, dmgfunc.RegNum, 1, 1);
build->Emit(OP_RESULT, 0, REGT_INT, dmgval.RegNum);
size_t notnulljump = build->Emit(OP_JMP, 0);
// Otherwise, use 0
build->BackpatchToHere(nulljump);
build->EmitLoadInt(dmgval.RegNum, 0);
build->BackpatchToHere(notnulljump);
return dmgval;
}
//========================================================================== //==========================================================================
// //
// //