mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- added an accessor to the actor defaults. This might have been possible with less work using a function but that would have necessitated some type casts when using it on subclasses.
- scriptified A_BarrelDestroy to test the above.
This commit is contained in:
parent
24925c88a8
commit
98fa3d2d93
8 changed files with 157 additions and 24 deletions
|
@ -1508,10 +1508,10 @@ void PPointer::SetOps()
|
|||
|
||||
bool PPointer::IsMatch(intptr_t id1, intptr_t id2) const
|
||||
{
|
||||
assert(id2 == 0);
|
||||
assert(id2 == 0 || id2 == 1);
|
||||
PType *pointat = (PType *)id1;
|
||||
|
||||
return pointat == PointedType;
|
||||
return pointat == PointedType && (!!id2) == IsConst;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -29,21 +29,3 @@
|
|||
#include "a_revenant.cpp"
|
||||
#include "a_scriptedmarine.cpp"
|
||||
|
||||
// The barrel of green goop ------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BarrelDestroy)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (dmflags2 & DF2_BARRELS_RESPAWN)
|
||||
{
|
||||
self->Height = self->GetDefault()->Height;
|
||||
self->renderflags |= RF_INVISIBLE;
|
||||
self->flags &= ~MF_SOLID;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->Destroy ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -683,6 +683,7 @@ xx(BuiltinNameToClass)
|
|||
xx(BuiltinFindMultiNameState)
|
||||
xx(BuiltinFindSingleNameState)
|
||||
xx(BuiltinHandleRuntimeState)
|
||||
xx(BuiltinGetDefault)
|
||||
xx(Damage)
|
||||
|
||||
// basic type names
|
||||
|
|
|
@ -5015,6 +5015,27 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
if (Identifier == NAME_Default)
|
||||
{
|
||||
if (ctx.Function->Variants[0].SelfClass == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Unable to access class defaults from static function");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (!ctx.Function->Variants[0].SelfClass->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FxExpression * x = new FxClassDefaults(new FxSelf(ScriptPosition), ScriptPosition);
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
// Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here...
|
||||
// see if the current class (if valid) defines something with this name.
|
||||
PSymbolTable *symtbl;
|
||||
|
@ -5348,6 +5369,95 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxClassDefaults::FxClassDefaults(FxExpression *X, const FScriptPosition &pos)
|
||||
: FxExpression(EFX_ClassDefaults, pos)
|
||||
{
|
||||
obj = X;
|
||||
EmitTail = false;
|
||||
}
|
||||
|
||||
FxClassDefaults::~FxClassDefaults()
|
||||
{
|
||||
SAFE_DELETE(obj);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PPrototype *FxClassDefaults::ReturnProto()
|
||||
{
|
||||
EmitTail = true;
|
||||
return FxExpression::ReturnProto();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxClassDefaults::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(obj, ctx);
|
||||
assert(obj->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)));
|
||||
ValueType = NewPointer(static_cast<PPointer*>(obj->ValueType)->PointedType, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinGetDefault(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam == 1);
|
||||
PARAM_POINTER_AT(0, obj, DObject);
|
||||
ACTION_RETURN_OBJECT(obj->GetClass()->Defaults);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
EmitParameter(build, obj, ScriptPosition);
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinGetDefault, BuiltinGetDefault);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
auto callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1);
|
||||
|
||||
if (EmitTail)
|
||||
{
|
||||
ExpEmit call;
|
||||
call.Final = true;
|
||||
return call;
|
||||
}
|
||||
|
||||
ExpEmit out(build, REGT_POINTER);
|
||||
build->Emit(OP_RESULT, 0, REGT_POINTER, out.RegNum);
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -5465,6 +5575,21 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
|||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(classx, ctx);
|
||||
|
||||
if (membervar->SymbolName == NAME_Default)
|
||||
{
|
||||
if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))
|
||||
|| !static_cast<PPointer *>(classx->ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
FxExpression * x = new FxClassDefaults(classx, ScriptPosition);
|
||||
classx = nullptr;
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType);
|
||||
|
@ -5581,7 +5706,6 @@ FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition
|
|||
: FxStructMember(x, mem, pos)
|
||||
{
|
||||
ExprType = EFX_ClassMember;
|
||||
//if (classx->IsDefaultObject()) Readonly=true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -355,12 +355,14 @@ public:
|
|||
class FxClassDefaults : public FxExpression
|
||||
{
|
||||
FxExpression *obj;
|
||||
bool EmitTail;
|
||||
|
||||
public:
|
||||
FxClassDefaults(FxExpression*, const FScriptPosition &);
|
||||
FxClassDefaults(FxExpression *, const FScriptPosition &);
|
||||
~FxClassDefaults();
|
||||
PPrototype *ReturnProto();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
bool IsDefaultObject() const;
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -224,6 +224,14 @@ dottable_id(X) ::= dottable_id(A) DOT IDENTIFIER(B).
|
|||
A->AppendSibling(id2);
|
||||
X = A; /*X-overwrites-A*/
|
||||
}
|
||||
dottable_id(X) ::= dottable_id(A) DOT DEFAULT.
|
||||
{
|
||||
NEW_AST_NODE(Identifier,id2,A);
|
||||
id2->Id = NAME_Default;
|
||||
A->AppendSibling(id2);
|
||||
X = A; /*X-overwrites-A*/
|
||||
}
|
||||
|
||||
// a bit of a hack to allow the 'color' token to be used inside default properties.
|
||||
// as a variable name it is practically meaningless because it cannot defined
|
||||
// as such anywhere so it will always produce an error during processing.
|
||||
|
|
|
@ -357,7 +357,6 @@ class Actor : Thinker native
|
|||
native int A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class<Actor> pufftype = "BulletPuff", name damagetype = "none");
|
||||
native void A_Stop();
|
||||
native void A_Respawn(int flags = 1);
|
||||
native void A_BarrelDestroy();
|
||||
native void A_QueueCorpse();
|
||||
native void A_DeQueueCorpse();
|
||||
native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = null);
|
||||
|
|
|
@ -34,6 +34,23 @@ class ExplosiveBarrel : Actor
|
|||
}
|
||||
}
|
||||
|
||||
extend class Actor
|
||||
{
|
||||
void A_BarrelDestroy()
|
||||
{
|
||||
if (GetCVar("sv_barrelrespawn"))
|
||||
{
|
||||
Height = Default.Height;
|
||||
bInvisible = true;
|
||||
bSolid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bullet puff -------------------------------------------------------------
|
||||
|
||||
class BulletPuff : Actor
|
||||
|
|
Loading…
Reference in a new issue