From b91ed5dc5da371cf51722ea6d5f2229712285d59 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Thu, 5 May 2016 18:33:36 -0500 Subject: [PATCH] Added GetZAt DECORATE function. - float GetZAt(x, y, angle, flags, pick_pointer); - Gets the floor z at x distance ahead and y distance to the side in relative form from the calling actor pointer. Flags are as follows (GZF_ prefix): - CEILING: Returns the ceiling z instead of floor. - ABSOLUTEPOS: x and y are absolute positions. - ABSOLUTEANG: angle parameter does not add the pointer's angle to the angle parameter. --- src/thingdef/thingdef_codeptr.cpp | 71 ++++++++++++++++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + wadsrc/static/actors/constants.txt | 8 ++++ 3 files changed, 80 insertions(+) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 677687f3e0..4ceb2b6f49 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -386,6 +386,77 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetGibHealth) return 0; } +//========================================================================== +// +// GetZAt +// +// NON-ACTION function to get the floor or ceiling z at (x, y) with +// relativity being an option. +//========================================================================== +enum GZFlags +{ + GZF_ABSOLUTEPOS = 1, + GZF_ABSOLUTEANG = 1 << 1, + GZF_CEILING = 1 << 2, +}; + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetZAt) +{ + if (numret > 0) + { + assert(ret != NULL); + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_OPT(px) { px = 0.; } + PARAM_FLOAT_OPT(py) { py = 0.; } + PARAM_ANGLE_OPT(angle) { angle = 0.; } + PARAM_INT_OPT(flags) { flags = 0; } + PARAM_INT_OPT(pick_pointer) { pick_pointer = AAPTR_DEFAULT; } + + AActor *mobj = COPY_AAPTR(self, pick_pointer); + if (mobj == nullptr) + { + ret->SetFloat(0); + } + else + { + DVector2 pos = { px, py }; + int secnum; + double z = 0.; + + if (!(flags & GZF_ABSOLUTEPOS)) + { + if (!(flags & GZF_ABSOLUTEANG)) + { + angle += mobj->Angles.Yaw; + } + + double s = angle.Sin(); + double c = angle.Cos(); + pos = mobj->Vec2Offset(pos.X * c + pos.Y * s, pos.X * s - pos.Y * c); + } + + secnum = int(P_PointInSector(pos.X, pos.Y) - sectors); + + if (secnum >= 0) + { + if (flags & GZF_CEILING) + { + //z = mobj->Sector->ceilingplane.ZatPoint(pos.X, pos.Y); + z = sectors[secnum].ceilingplane.ZatPoint(pos); + } + else + { + //z = mobj->Sector->floorplane.ZatPoint(pos.X, pos.Y); + z = sectors[secnum].floorplane.ZatPoint(pos); + } + } + ret->SetFloat(z); + return 1; + } + } + return 0; +} + //=========================================================================== // // __decorate_internal_state__ diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 8b35be30d0..44ebb1dc32 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -43,6 +43,7 @@ ACTOR Actor native //: Thinker native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); native float GetDistance(bool checkz, int ptr = AAPTR_DEFAULT); native float GetAngle(bool relative, int ptr = AAPTR_DEFAULT); + native float GetZAt(float px = 0, float py = 0, float angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); native int GetSpawnHealth(); native int GetGibHealth(); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 1922194edb..a639799aff 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -550,3 +550,11 @@ enum FMDF_INTERPOLATE = 1 << 1, FMDF_NOANGLE = 1 << 2, }; + +// Flags for GetZAt +enum +{ + GZF_ABSOLUTEPOS = 1, + GZF_ABSOLUTEANG = 1 << 1, + GZF_CEILING = 1 << 2, +};