mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
A more "general purpose" line trace function. Far from a complete ZScript interface with Trace(), though.
This commit is contained in:
parent
3f45f938d6
commit
69e8c9ec6e
5 changed files with 230 additions and 0 deletions
25
src/p_linetracedata.h
Normal file
25
src/p_linetracedata.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef P_LTRACEDATA_H
|
||||
#define P_LTRACEDATA_H
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Structure for passing detailed results of LineTrace to ZScript
|
||||
//
|
||||
//============================================================================
|
||||
struct FLineTraceData
|
||||
{
|
||||
AActor *HitActor;
|
||||
line_t *HitLine;
|
||||
sector_t *HitSector;
|
||||
F3DFloor *Hit3DFloor;
|
||||
FTextureID HitTexture;
|
||||
DVector3 HitLocation;
|
||||
double Distance;
|
||||
int NumPortals;
|
||||
int LineSide;
|
||||
int LinePart;
|
||||
int SectorPlane;
|
||||
ETraceResult HitType;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -336,6 +336,18 @@ enum // P_LineAttack flags
|
|||
AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0);
|
||||
AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0);
|
||||
|
||||
enum // P_LineTrace flags
|
||||
{
|
||||
TRF_ABSPOSITION = 1,
|
||||
TRF_ABSOFFSET = 2,
|
||||
TRF_THRUSPECIES = 4,
|
||||
TRF_THRUACTORS = 8,
|
||||
TRF_THRUBLOCK = 16,
|
||||
TRF_THRUHITSCAN = 32,
|
||||
TRF_NOSKY = 64,
|
||||
TRF_ALLACTORS = 128,
|
||||
};
|
||||
|
||||
void P_TraceBleed(int damage, const DVector3 &pos, AActor *target, DAngle angle, DAngle pitch);
|
||||
void P_TraceBleed(int damage, AActor *target, DAngle angle, DAngle pitch);
|
||||
|
||||
|
|
154
src/p_map.cpp
154
src/p_map.cpp
|
@ -79,6 +79,7 @@
|
|||
#include "p_terrain.h"
|
||||
#include "p_trace.h"
|
||||
#include "p_checkposition.h"
|
||||
#include "p_linetracedata.h"
|
||||
#include "r_utility.h"
|
||||
#include "p_blockmap.h"
|
||||
#include "p_3dmidtex.h"
|
||||
|
@ -4814,6 +4815,159 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack)
|
|||
return numret;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_LineTrace
|
||||
//
|
||||
//==========================================================================
|
||||
struct LineTraceData
|
||||
{
|
||||
AActor *Caller;
|
||||
bool ThruSpecies;
|
||||
bool ThruActors;
|
||||
int NumPortals;
|
||||
};
|
||||
|
||||
static ETraceStatus CheckLineTrace(FTraceResults &res, void *userdata)
|
||||
{
|
||||
LineTraceData *TData = (LineTraceData *)userdata;
|
||||
if ( res.HitType == TRACE_CrossingPortal )
|
||||
{
|
||||
TData->NumPortals++;
|
||||
return TRACE_Skip;
|
||||
}
|
||||
if ( res.HitType != TRACE_HitActor )
|
||||
{
|
||||
return TRACE_Stop;
|
||||
}
|
||||
if ( (TData->ThruActors) || (TData->ThruSpecies && res.Actor->GetSpecies() == TData->Caller->GetSpecies()) )
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
return TRACE_Stop;
|
||||
}
|
||||
|
||||
bool P_LineTrace(AActor *t1, DAngle angle, double distance,
|
||||
DAngle pitch, int flags, double sz, double offsetforward,
|
||||
double offsetside, FLineTraceData *outdata)
|
||||
{
|
||||
FTraceResults trace;
|
||||
LineTraceData TData;
|
||||
TData.Caller = t1;
|
||||
TData.ThruSpecies = (flags & TRF_THRUSPECIES);
|
||||
TData.ThruActors = (flags & TRF_THRUACTORS);
|
||||
TData.NumPortals = 0;
|
||||
DVector3 direction;
|
||||
double pc = pitch.Cos();
|
||||
direction = { pc * angle.Cos(), pc * angle.Sin(), -pitch.Sin() };
|
||||
DVector3 startpos;
|
||||
double startz = t1->Z() - t1->Floorclip;
|
||||
startz += sz;
|
||||
if ( flags & TRF_ABSPOSITION )
|
||||
{
|
||||
startpos = DVector3(offsetforward, offsetside, sz);
|
||||
}
|
||||
else if ( flags & TRF_ABSOFFSET )
|
||||
{
|
||||
startpos = t1->Vec2OffsetZ(offsetforward, offsetside, startz);
|
||||
}
|
||||
else if ( (offsetforward == 0.0) && (offsetside == 0.0) )
|
||||
{
|
||||
startpos = t1->PosAtZ(startz);
|
||||
}
|
||||
else
|
||||
{
|
||||
const double s = angle.Sin();
|
||||
const double c = angle.Cos();
|
||||
startpos = t1->Vec2OffsetZ(offsetforward * c + offsetside * s, offsetforward * s - offsetside * c, startz);
|
||||
}
|
||||
|
||||
ActorFlags aflags = (flags & TRF_ALLACTORS) ? ActorFlags::FromInt(0xFFFFFFFF) : MF_SHOOTABLE;
|
||||
int lflags = 0;
|
||||
if ( !(lflags & TRF_THRUBLOCK) ) lflags |= ML_BLOCKEVERYTHING;
|
||||
if ( !(lflags & TRF_THRUHITSCAN) ) lflags |= ML_BLOCKHITSCAN;
|
||||
int tflags = TRACE_ReportPortals;
|
||||
if ( flags & TRF_NOSKY ) tflags |= TRACE_NoSky;
|
||||
|
||||
// Do trace
|
||||
bool ret = Trace(startpos, t1->Sector, direction, distance, aflags, lflags, t1, trace, tflags, CheckLineTrace, &TData);
|
||||
if ( outdata )
|
||||
{
|
||||
memset(outdata,0,sizeof(*outdata));
|
||||
outdata->HitActor = trace.Actor;
|
||||
outdata->HitLine = trace.Line;
|
||||
outdata->HitSector = trace.Sector;
|
||||
outdata->Hit3DFloor = trace.ffloor;
|
||||
switch ( trace.HitType )
|
||||
{
|
||||
case TRACE_HitFloor:
|
||||
outdata->SectorPlane = 0;
|
||||
outdata->HitTexture = trace.Sector->planes[0].Texture;
|
||||
break;
|
||||
case TRACE_HitCeiling:
|
||||
outdata->SectorPlane = 1;
|
||||
outdata->HitTexture = trace.Sector->planes[1].Texture;
|
||||
break;
|
||||
case TRACE_HitWall:
|
||||
outdata->LineSide = trace.Side;
|
||||
int txpart;
|
||||
switch ( trace.Tier )
|
||||
{
|
||||
case TIER_Middle:
|
||||
outdata->LinePart = 1;
|
||||
outdata->HitTexture = trace.Line->sidedef[trace.Side]->textures[1].texture;
|
||||
break;
|
||||
case TIER_Upper:
|
||||
outdata->LinePart = 0;
|
||||
outdata->HitTexture = trace.Line->sidedef[trace.Side]->textures[0].texture;
|
||||
break;
|
||||
case TIER_Lower:
|
||||
outdata->LinePart = 2;
|
||||
outdata->HitTexture = trace.Line->sidedef[trace.Side]->textures[2].texture;
|
||||
break;
|
||||
case TIER_FFloor:
|
||||
txpart = (trace.ffloor->flags & FF_UPPERTEXTURE) ? 0 : (trace.ffloor->flags & FF_LOWERTEXTURE) ? 2 : 1;
|
||||
outdata->HitTexture = trace.ffloor->master->sidedef[0]->textures[txpart].texture;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
outdata->HitLocation = trace.HitPos;
|
||||
outdata->Distance = trace.Distance;
|
||||
outdata->NumPortals = TData.NumPortals;
|
||||
outdata->HitType = trace.HitType;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitActor);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitLine);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitSector);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, Hit3DFloor);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitTexture);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitLocation);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, Distance);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, NumPortals);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, LineSide);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, LinePart);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, SectorPlane);
|
||||
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitType);
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, LineTrace)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_ANGLE(angle);
|
||||
PARAM_FLOAT(distance);
|
||||
PARAM_ANGLE(pitch);
|
||||
PARAM_INT_DEF(flags);
|
||||
PARAM_FLOAT_DEF(offsetz);
|
||||
PARAM_FLOAT_DEF(offsetforward);
|
||||
PARAM_FLOAT_DEF(offsetside);
|
||||
PARAM_POINTER_DEF(data, FLineTraceData);
|
||||
ACTION_RETURN_BOOL(P_LineTrace(self,angle,distance,pitch,flags,offsetz,offsetforward,offsetside,data));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_LinePickActor
|
||||
|
|
|
@ -29,6 +29,32 @@ struct FCheckPosition
|
|||
native void ClearLastRipped();
|
||||
}
|
||||
|
||||
struct FLineTraceData
|
||||
{
|
||||
enum ETraceResult
|
||||
{
|
||||
TRACE_HitNone,
|
||||
TRACE_HitFloor,
|
||||
TRACE_HitCeiling,
|
||||
TRACE_HitWall,
|
||||
TRACE_HitActor,
|
||||
TRACE_CrossingPortal
|
||||
};
|
||||
|
||||
Actor HitActor;
|
||||
Line HitLine;
|
||||
Sector HitSector;
|
||||
F3DFloor Hit3DFloor;
|
||||
TextureID HitTexture;
|
||||
Vector3 HitLocation;
|
||||
double Distance;
|
||||
int NumPortals;
|
||||
int LineSide;
|
||||
int LinePart;
|
||||
int SectorPlane;
|
||||
int HitType;
|
||||
}
|
||||
|
||||
struct LinkContext
|
||||
{
|
||||
voidptr sector_list; // really msecnode but that's not exported yet.
|
||||
|
@ -602,6 +628,7 @@ class Actor : Thinker native
|
|||
native void PoisonMobj (Actor inflictor, Actor source, int damage, int duration, int period, Name type);
|
||||
native double AimLineAttack(double angle, double distance, out FTranslatedLineTarget pLineTarget = null, double vrange = 0., int flags = 0, Actor target = null, Actor friender = null);
|
||||
native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class<Actor> pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0., double offsetforward = 0., double offsetside = 0.);
|
||||
native bool LineTrace(double angle, double distance, double pitch, int flags = 0, double offsetz = 0., double offsetforward = 0., double offsetside = 0., out FLineTraceData data = null);
|
||||
native bool CheckSight(Actor target, int flags = 0);
|
||||
native bool IsVisible(Actor other, bool allaround, LookExParams params = null);
|
||||
native bool HitFriend();
|
||||
|
|
|
@ -897,6 +897,18 @@ enum ELineAttackFlags
|
|||
LAF_ABSPOSITION = 1 << 7,
|
||||
}
|
||||
|
||||
enum ELineTraceFlags
|
||||
{
|
||||
TRF_ABSPOSITION = 1,
|
||||
TRF_ABSOFFSET = 2,
|
||||
TRF_THRUSPECIES = 4,
|
||||
TRF_THRUACTORS = 8,
|
||||
TRF_THRUBLOCK = 16,
|
||||
TRF_THRUHITSCAN = 32,
|
||||
TRF_NOSKY = 64,
|
||||
TRF_ALLACTORS = 128,
|
||||
}
|
||||
|
||||
const DEFMELEERANGE = 64;
|
||||
const SAWRANGE = (64.+(1./65536.)); // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states)
|
||||
const MISSILERANGE = (32*64);
|
||||
|
|
Loading…
Reference in a new issue