- 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:
Randy Heit 2013-06-05 02:15:21 +00:00
parent 5a00f4b59a
commit e32e44209e
3 changed files with 97 additions and 23 deletions

View file

@ -755,6 +755,48 @@ CCMD (spray)
Net_WriteString (argv[1]); 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 class ADecal : public AActor
{ {
DECLARE_CLASS (ADecal, AActor); DECLARE_CLASS (ADecal, AActor);
@ -767,9 +809,6 @@ IMPLEMENT_CLASS (ADecal)
void ADecal::BeginPlay () void ADecal::BeginPlay ()
{ {
const FDecalTemplate *tpl; const FDecalTemplate *tpl;
FTraceResults trace;
DBaseDecal *decal;
side_t *wall;
Super::BeginPlay (); Super::BeginPlay ();
@ -781,31 +820,13 @@ void ADecal::BeginPlay ()
if (!tpl->PicNum.Exists()) if (!tpl->PicNum.Exists())
{ {
Printf("Decal actor at (%d,%d) does not have a valid texture\n", x>>FRACBITS, y>>FRACBITS); Printf("Decal actor at (%d,%d) does not have a valid texture\n", x>>FRACBITS, y>>FRACBITS);
} }
else else
{ {
// Look for a wall within 64 units behind the actor. If none can be // 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 // found, then no decal is created, and this actor is destroyed
// without effectively doing anything. // without effectively doing anything.
Trace (x, y, z, Sector, if (NULL == ShootDecal(tpl, this, Sector, x, y, z, angle + ANGLE_180, 64*FRACUNIT, true))
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
{ {
DPrintf ("Could not find a wall to stick decal to at (%d,%d)\n", x>>FRACBITS, y>>FRACBITS); DPrintf ("Could not find a wall to stick decal to at (%d,%d)\n", x>>FRACBITS, y>>FRACBITS);
} }

View file

@ -9,7 +9,8 @@ struct vertex_t;
struct side_t; struct side_t;
struct F3DFloor; 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 class DBaseDecal : public DThinker
{ {

View file

@ -73,6 +73,7 @@
#include "po_man.h" #include "po_man.h"
#include "actorptrselect.h" #include "actorptrselect.h"
#include "farchive.h" #include "farchive.h"
#include "decallib.h"
#include "g_shared/a_pickups.h" #include "g_shared/a_pickups.h"
@ -111,6 +112,10 @@ FRandom pr_acs ("ACS");
#define NOT_FLOOR 8 #define NOT_FLOOR 8
#define NOT_CEILING 16 #define NOT_CEILING 16
// SpawnDecal flags
#define SDF_ABSANGLE 1
#define SDF_PERMANENT 2
struct CallReturn struct CallReturn
{ {
CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, bool discard, unsigned int runaway) CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, bool discard, unsigned int runaway)
@ -4192,6 +4197,7 @@ enum EACSFunctions
ACSF_GetWeapon, ACSF_GetWeapon,
ACSF_SoundVolume, ACSF_SoundVolume,
ACSF_PlayActorSound, ACSF_PlayActorSound,
ACSF_SpawnDecal,
// ZDaemon // ZDaemon
ACSF_GetTeamScore = 19620, // (int team) ACSF_GetTeamScore = 19620, // (int team)
@ -4440,6 +4446,17 @@ static int SetCVar(AActor *activator, const char *cvarname, int value, bool is_s
return 1; 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) int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const SDWORD *stack, int stackdepth)
{ {
AActor *actor; AActor *actor;
@ -5141,6 +5158,41 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
return GlobalACSStrings.AddString(activator->player->ReadyWeapon->GetClass()->TypeName.GetChars(), stack, stackdepth); 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: default:
break; break;
} }