mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 04:51:19 +00:00
- Added SpawnDecal ACS function:
int SpawnDecal(int tid, str decalname, int flags, fixed angle, int zoffset, int distance) Traces a line from tid's actor until hitting a wall, then creates a decal there. Returns the number of decals spawned. * tid = Which actor(s) to start the trace at. * decalname = Which decal to spawn. * flags = * SDF_ABSANGLE = Angle parameter is an absolute angle. Otherwise, it's relative to the origin actor's angle. * SDF_PERMANENT = Decal ignores cl_maxdecals. Otherwise, it will eventually disappear. * angle = Direction in which to search for a wall. Defaults to 0.0. * zoffset = Offset from the middle of the origin actor for the Z height of the decal. Defaults to 0. * distance = Maximum distance to search for a wall. Defaults to 64. SVN r4330 (trunk)
This commit is contained in:
parent
5a00f4b59a
commit
e32e44209e
3 changed files with 97 additions and 23 deletions
|
@ -755,6 +755,48 @@ CCMD (spray)
|
|||
Net_WriteString (argv[1]);
|
||||
}
|
||||
|
||||
DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, fixed_t x, fixed_t y, fixed_t z, angle_t angle, fixed_t tracedist, bool permanent)
|
||||
{
|
||||
if (tpl == NULL || (tpl = tpl->GetDecal()) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FTraceResults trace;
|
||||
DBaseDecal *decal;
|
||||
side_t *wall;
|
||||
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
|
||||
Trace(x, y, z, sec,
|
||||
finecosine[angle], finesine[angle], 0,
|
||||
tracedist, 0, 0, NULL, trace, TRACE_NoSky);
|
||||
|
||||
if (trace.HitType == TRACE_HitWall)
|
||||
{
|
||||
if (permanent)
|
||||
{
|
||||
decal = new DBaseDecal(trace.Z);
|
||||
wall = trace.Line->sidedef[trace.Side];
|
||||
decal->StickToWall(wall, trace.X, trace.Y, trace.ffloor);
|
||||
tpl->ApplyToDecal(decal, wall);
|
||||
// Spread decal to nearby walls if it does not all fit on this one
|
||||
if (cl_spreaddecals)
|
||||
{
|
||||
decal->Spread(tpl, wall, trace.X, trace.Y, trace.Z, trace.ffloor);
|
||||
}
|
||||
return decal;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DImpactDecal::StaticCreate(tpl,
|
||||
trace.X, trace.Y, trace.Z,
|
||||
trace.Line->sidedef[trace.Side], NULL);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
class ADecal : public AActor
|
||||
{
|
||||
DECLARE_CLASS (ADecal, AActor);
|
||||
|
@ -767,9 +809,6 @@ IMPLEMENT_CLASS (ADecal)
|
|||
void ADecal::BeginPlay ()
|
||||
{
|
||||
const FDecalTemplate *tpl;
|
||||
FTraceResults trace;
|
||||
DBaseDecal *decal;
|
||||
side_t *wall;
|
||||
|
||||
Super::BeginPlay ();
|
||||
|
||||
|
@ -781,31 +820,13 @@ void ADecal::BeginPlay ()
|
|||
if (!tpl->PicNum.Exists())
|
||||
{
|
||||
Printf("Decal actor at (%d,%d) does not have a valid texture\n", x>>FRACBITS, y>>FRACBITS);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for a wall within 64 units behind the actor. If none can be
|
||||
// found, then no decal is created, and this actor is destroyed
|
||||
// without effectively doing anything.
|
||||
Trace (x, y, z, Sector,
|
||||
finecosine[(angle+ANGLE_180)>>ANGLETOFINESHIFT],
|
||||
finesine[(angle+ANGLE_180)>>ANGLETOFINESHIFT], 0,
|
||||
64*FRACUNIT, 0, 0, NULL, trace, TRACE_NoSky);
|
||||
|
||||
if (trace.HitType == TRACE_HitWall)
|
||||
{
|
||||
decal = new DBaseDecal (this);
|
||||
wall = trace.Line->sidedef[trace.Side];
|
||||
decal->StickToWall (wall, trace.X, trace.Y, trace.ffloor);
|
||||
tpl->ApplyToDecal (decal, wall);
|
||||
// Spread decal to nearby walls if it does not all fit on this one
|
||||
if (cl_spreaddecals)
|
||||
{
|
||||
decal->Spread (tpl, wall, trace.X, trace.Y, z, trace.ffloor);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (NULL == ShootDecal(tpl, this, Sector, x, y, z, angle + ANGLE_180, 64*FRACUNIT, true))
|
||||
{
|
||||
DPrintf ("Could not find a wall to stick decal to at (%d,%d)\n", x>>FRACBITS, y>>FRACBITS);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ struct vertex_t;
|
|||
struct side_t;
|
||||
struct F3DFloor;
|
||||
|
||||
extern void P_SpawnDirt (AActor *actor, fixed_t radius);
|
||||
void P_SpawnDirt (AActor *actor, fixed_t radius);
|
||||
class DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, fixed_t x, fixed_t y, fixed_t z, angle_t angle, fixed_t tracedist, bool permanent);
|
||||
|
||||
class DBaseDecal : public DThinker
|
||||
{
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "po_man.h"
|
||||
#include "actorptrselect.h"
|
||||
#include "farchive.h"
|
||||
#include "decallib.h"
|
||||
|
||||
#include "g_shared/a_pickups.h"
|
||||
|
||||
|
@ -111,6 +112,10 @@ FRandom pr_acs ("ACS");
|
|||
#define NOT_FLOOR 8
|
||||
#define NOT_CEILING 16
|
||||
|
||||
// SpawnDecal flags
|
||||
#define SDF_ABSANGLE 1
|
||||
#define SDF_PERMANENT 2
|
||||
|
||||
struct CallReturn
|
||||
{
|
||||
CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, bool discard, unsigned int runaway)
|
||||
|
@ -4192,6 +4197,7 @@ enum EACSFunctions
|
|||
ACSF_GetWeapon,
|
||||
ACSF_SoundVolume,
|
||||
ACSF_PlayActorSound,
|
||||
ACSF_SpawnDecal,
|
||||
|
||||
// ZDaemon
|
||||
ACSF_GetTeamScore = 19620, // (int team)
|
||||
|
@ -4440,6 +4446,17 @@ static int SetCVar(AActor *activator, const char *cvarname, int value, bool is_s
|
|||
return 1;
|
||||
}
|
||||
|
||||
static bool DoSpawnDecal(AActor *actor, const FDecalTemplate *tpl, int flags, angle_t angle, fixed_t zofs, fixed_t distance)
|
||||
{
|
||||
if (!(flags & SDF_ABSANGLE))
|
||||
{
|
||||
angle += actor->angle;
|
||||
}
|
||||
return NULL != ShootDecal(tpl, actor, actor->Sector, actor->x, actor->y,
|
||||
actor->z + (actor->height>>1) - actor->floorclip + actor->GetBobOffset() + zofs,
|
||||
angle, distance, !!(flags & SDF_PERMANENT));
|
||||
}
|
||||
|
||||
int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const SDWORD *stack, int stackdepth)
|
||||
{
|
||||
AActor *actor;
|
||||
|
@ -5141,6 +5158,41 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
return GlobalACSStrings.AddString(activator->player->ReadyWeapon->GetClass()->TypeName.GetChars(), stack, stackdepth);
|
||||
}
|
||||
|
||||
case ACSF_SpawnDecal:
|
||||
// int SpawnDecal(int tid, str decalname, int flags, fixed angle, int zoffset, int distance)
|
||||
// Returns number of decals spawned (not including spreading)
|
||||
{
|
||||
int count = 0;
|
||||
const FDecalTemplate *tpl = DecalLibrary.GetDecalByName(FBehavior::StaticLookupString(args[1]));
|
||||
if (tpl != NULL)
|
||||
{
|
||||
int flags = (argCount > 2) ? args[2] : 0;
|
||||
angle_t angle = (argCount > 3) ? (args[3] << FRACBITS) : 0;
|
||||
fixed_t zoffset = (argCount > 4) ? (args[4] << FRACBITS) : 0;
|
||||
fixed_t distance = (argCount > 5) ? (args[5] << FRACBITS) : 64*FRACUNIT;
|
||||
|
||||
if (args[0] == 0)
|
||||
{
|
||||
if (activator != NULL)
|
||||
{
|
||||
count += DoSpawnDecal(activator, tpl, flags, angle, zoffset, distance);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FActorIterator it(args[0]);
|
||||
AActor *actor;
|
||||
|
||||
while ((actor = it.Next()) != NULL)
|
||||
{
|
||||
count += DoSpawnDecal(actor, tpl, flags, angle, zoffset, distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue