diff --git a/src/namedef.h b/src/namedef.h index a4c8da6388..1e7fbd0d3a 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -298,6 +298,7 @@ xx(Abs) xx(ACS_NamedExecuteWithResult) xx(CallACS) xx(Sqrt) +xx(CheckClass) // Various actor names which are used internally xx(MapSpot) diff --git a/src/thingdef/thingdef_function.cpp b/src/thingdef/thingdef_function.cpp index 2858e9a86e..9bf80dcaaf 100644 --- a/src/thingdef/thingdef_function.cpp +++ b/src/thingdef/thingdef_function.cpp @@ -43,6 +43,8 @@ #include "tarray.h" #include "thingdef.h" #include "thingdef_exp.h" +#include "actor.h" +#include "actorptrselect.h" static TMap CreatorMap; @@ -185,3 +187,77 @@ public: GLOBALFUNCTION_ADDER(Sqrt); +//========================================================================== +// +// Function: checkclass +// +//========================================================================== + +class FxGlobalFunctionCall_CheckClass : public FxGlobalFunctionCall +{ + public: + GLOBALFUNCTION_DEFINE(CheckClass); + + FxExpression *Resolve(FCompileContext& ctx) + { + CHECKRESOLVED(); + + if (!ResolveArgs(ctx, 1, 3, false)) + return NULL; + + for (int i = ArgList->Size(); i > 1;) + { + if (!(*ArgList)[--i]->ValueType.isNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); + delete this; + return NULL; + } + } + + switch ((*ArgList)[0]->ValueType.Type) + { + case VAL_Class: case VAL_Name:break; + default: + ScriptPosition.Message(MSG_ERROR, "actor class expected for parameter"); + delete this; + return NULL; + } + + ValueType = VAL_Float; + return this; + } + + ExpVal EvalExpression(AActor *self) + { + ExpVal ret; + ret.Type = VAL_Int; + + const PClass * checkclass; + { + ExpVal v = (*ArgList)[0]->EvalExpression(self); + checkclass = v.GetClass(); + if (!checkclass) + { + checkclass = PClass::FindClass(v.GetName()); + if (!checkclass) { ret.Int = 0; return ret; } + } + } + + bool match_superclass = false; + int pick_pointer = AAPTR_DEFAULT; + + switch (ArgList->Size()) + { + case 3: match_superclass = (*ArgList)[2]->EvalExpression(self).GetBool(); + case 2: pick_pointer = (*ArgList)[1]->EvalExpression(self).GetInt(); + } + + self = COPY_AAPTR(self, pick_pointer); + if (!self){ ret.Int = 0; return ret; } + ret.Int = match_superclass ? checkclass->IsAncestorOf(self->GetClass()) : checkclass == self->GetClass(); + return ret; + } + }; + +GLOBALFUNCTION_ADDER(CheckClass); \ No newline at end of file