From a7ff62316d92e3bafc1f9c63c2d625e26bc2fdc8 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sat, 20 Jan 2018 15:37:03 +0200 Subject: [PATCH] Exported Trace() interface to ZScript --- src/p_trace.cpp | 74 +++++++++++++++++++++++++++++++ src/p_trace.h | 10 +++++ wadsrc/static/zscript/base.txt | 81 ++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 8522e891a..8c991d101 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -42,6 +42,7 @@ #include "p_spec.h" #include "g_levellocals.h" #include "p_terrain.h" +#include "vm.h" //========================================================================== // @@ -948,3 +949,76 @@ static bool EditTraceResult (uint32_t flags, FTraceResults &res) } return true; } + +//========================================================================== +// +// [ZZ] here go the methods for the ZScript interface +// +//========================================================================== +IMPLEMENT_CLASS(DTracer, false, false) +DEFINE_FIELD_X(Tracer, DTracer, Results) + +// define TraceResults fields +DEFINE_FIELD_NAMED_X(TraceResults, FTraceResults, Sector, Sec) +DEFINE_FIELD_X(TraceResults, FTraceResults, HitTexture) +DEFINE_FIELD_X(TraceResults, FTraceResults, HitPos) +DEFINE_FIELD_X(TraceResults, FTraceResults, HitVector) +DEFINE_FIELD_X(TraceResults, FTraceResults, SrcFromTarget) +DEFINE_FIELD_X(TraceResults, FTraceResults, SrcAngleFromTarget) +DEFINE_FIELD_X(TraceResults, FTraceResults, Distance) +DEFINE_FIELD_X(TraceResults, FTraceResults, Fraction) +DEFINE_FIELD_NAMED_X(TraceResults, FTraceResults, Actor, Thing) +DEFINE_FIELD_NAMED_X(TraceResults, FTraceResults, Line, Linedef) +DEFINE_FIELD_X(TraceResults, FTraceResults, Side) +DEFINE_FIELD_X(TraceResults, FTraceResults, Tier) +DEFINE_FIELD_X(TraceResults, FTraceResults, unlinked) +DEFINE_FIELD_X(TraceResults, FTraceResults, HitType) +DEFINE_FIELD_X(TraceResults, FTraceResults, CrossedWater) +DEFINE_FIELD_X(TraceResults, FTraceResults, CrossedWaterPos) +DEFINE_FIELD_X(TraceResults, FTraceResults, Crossed3DWater) +DEFINE_FIELD_X(TraceResults, FTraceResults, Crossed3DWaterPos) + +DEFINE_ACTION_FUNCTION(DTracer, Trace) +{ + PARAM_SELF_PROLOGUE(DTracer); + /*bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, double maxDist, + ActorFlags ActorMask, uint32_t WallMask, AActor *ignore, FTraceResults &res, uint32_t traceFlags = 0, + ETraceStatus(*callback)(FTraceResults &res, void *) = NULL, void *callbackdata = NULL);*/ + PARAM_FLOAT(start_x); + PARAM_FLOAT(start_y); + PARAM_FLOAT(start_z); + PARAM_POINTER(sector, sector_t); + PARAM_FLOAT(direction_x); + PARAM_FLOAT(direction_y); + PARAM_FLOAT(direction_z); + PARAM_FLOAT(maxDist); + // actor flags and wall flags are not supported due to how flags are implemented on the ZScript side. + // say thanks to oversimplifying the user API. + PARAM_INT(traceFlags); + + // Trace(vector3 start, Sector sector, vector3 direction, double maxDist, ETraceFlags traceFlags) + bool res = Trace(DVector3(start_x, start_y, start_z), sector, DVector3(direction_x, direction_y, direction_z), maxDist, + (ActorFlag)0xFFFFFFFF, 0xFFFFFFFF, nullptr, self->Results, traceFlags, &DTracer::TraceCallback, self); + ACTION_RETURN_BOOL(res); +} + +ETraceStatus DTracer::TraceCallback(FTraceResults& res, void* pthis) +{ + DTracer* self = (DTracer*)pthis; + // "res" here should refer to self->Results anyway. + return self->CallZScriptCallback(); +} + +ETraceStatus DTracer::CallZScriptCallback() +{ + IFVIRTUAL(DTracer, TraceCallback) + { + int status; + VMReturn results[1] = { &status }; + VMValue params[1] = { (DTracer*)this }; + VMCall(func, params, 1, results, 1); + return (ETraceStatus)status; + } + + return TRACE_Stop; +} \ No newline at end of file diff --git a/src/p_trace.h b/src/p_trace.h index 914eee288..af4187f78 100644 --- a/src/p_trace.h +++ b/src/p_trace.h @@ -112,4 +112,14 @@ bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, d ActorFlags ActorMask, uint32_t WallMask, AActor *ignore, FTraceResults &res, uint32_t traceFlags = 0, ETraceStatus(*callback)(FTraceResults &res, void *) = NULL, void *callbackdata = NULL); +// [ZZ] this is the object that's used for ZScript +class DTracer : public DObject +{ + DECLARE_CLASS(DTracer, DObject) +public: + FTraceResults Results; + static ETraceStatus TraceCallback(FTraceResults& res, void* pthis); + ETraceStatus CallZScriptCallback(); +}; + #endif //__P_TRACE_H__ diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index bf5edf6ca..1b32b82d3 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -460,6 +460,87 @@ class BlockLinesIterator : Object native native bool Next(); } +enum ETraceStatus +{ + TRACE_Stop, // stop the trace, returning this hit + TRACE_Continue, // continue the trace, returning this hit if there are none further along + TRACE_Skip, // continue the trace; do not return this hit + TRACE_Abort // stop the trace, returning no hits +} + +enum ETraceFlags +{ + TRACE_NoSky = 1, // Hitting the sky returns TRACE_HitNone + TRACE_PCross = 2, // Trigger SPAC_PCROSS lines + TRACE_Impact = 4, // Trigger SPAC_IMPACT lines + TRACE_PortalRestrict = 8, // Cannot go through portals without a static link offset. + TRACE_ReportPortals = 16 // Report any portal crossing to the TraceCallback +} + + +enum ETraceResult +{ + TRACE_HitNone, + TRACE_HitFloor, + TRACE_HitCeiling, + TRACE_HitWall, + TRACE_HitActor, + TRACE_CrossingPortal +} + +enum ELineTier +{ + TIER_Middle, + TIER_Upper, + TIER_Lower, + TIER_FFloor +} + +struct TraceResults native +{ + native Sector Sec; // originally called "Sector". cannot be named like this in ZScript. + native TextureID HitTexture; + native vector3 HitPos; + native vector3 HitVector; + native vector3 SrcFromTarget; + native double SrcAngleFromTarget; + + native double Distance; + native double Fraction; + + native Actor Thing; // valid if hit an actor. // originally called "Actor". + + native Line Linedef; // valid if hit a line // originally called "Line". + native uint8 Side; + native uint8 Tier; // see Tracer.ELineTier + native bool unlinked; // passed through a portal without static offset. + + native ETraceResult HitType; + // F3DFloor *ffloor; + + native Sector CrossedWater; // For Boom-style, Transfer_Heights-based deep water + native vector3 CrossedWaterPos; // remember the position so that we can use it for spawning the splash + native Sector Crossed3DWater; // For 3D floor-based deep water + native vector3 Crossed3DWaterPos; +} + +class Tracer : Object native +{ + native @TraceResults Results; + native bool Trace(vector3 start, Sector sec, vector3 direction, double maxDist, ETraceFlags traceFlags); + + virtual ETraceStatus TraceCallback() + { + // Normally you would examine Results.HitType (for ETraceResult), and determine either: + // - stop tracing and return the entity that was found (return TRACE_Stop) + // - ignore some object, like noclip, e.g. only count solid walls and floors, and ignore actors (return TRACE_Skip) + // - find last object of some type (return TRACE_Continue) + // - stop tracing entirely and assume we found nothing (return TRACE_Abort) + // TRACE_Abort and TRACE_Continue are of limited use in scripting. + + return TRACE_Stop; // default callback returns first hit, whatever it is. + } +} struct DropItem native {