- Updated scripting branch to latest version in trunk.
SVN r4337 (scripting)
This commit is contained in:
commit
459ad5abff
282 changed files with 15968 additions and 3535 deletions
|
|
@ -68,6 +68,8 @@
|
|||
#include "g_shared/a_specialspot.h"
|
||||
#include "actorptrselect.h"
|
||||
#include "m_bbox.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "p_trace.h"
|
||||
|
||||
|
||||
static FRandom pr_camissile ("CustomActorfire");
|
||||
|
|
@ -349,8 +351,8 @@ static void DoAttack (AActor *self, bool domelee, bool domissile,
|
|||
{
|
||||
int damage = pr_camelee.HitDice(MeleeDamage);
|
||||
if (MeleeSound) S_Sound (self, CHAN_WEAPON, MeleeSound, 1, ATTN_NORM);
|
||||
P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (damage, self->target, self);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
else if (domissile && MissileType != NULL)
|
||||
{
|
||||
|
|
@ -366,7 +368,7 @@ static void DoAttack (AActor *self, bool domelee, bool domissile,
|
|||
{
|
||||
missile->tracer=self->target;
|
||||
}
|
||||
P_CheckMissileSpawn(missile);
|
||||
P_CheckMissileSpawn(missile, self->radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -919,8 +921,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust)
|
|||
|
||||
bool sourcenothrust = false;
|
||||
|
||||
if (force <= 0) force = 128;
|
||||
if (distance <= 0) distance = force;
|
||||
if (force == 0) force = 128;
|
||||
if (distance <= 0) distance = abs(force);
|
||||
|
||||
// Temporarily negate MF2_NODMGTHRUST on the shooter, since it renders this function useless.
|
||||
if (!(flags & RTF_NOTMISSILE) && self->target != NULL && self->target->flags2 & MF2_NODMGTHRUST)
|
||||
|
|
@ -928,7 +930,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust)
|
|||
sourcenothrust = true;
|
||||
self->target->flags2 &= ~MF2_NODMGTHRUST;
|
||||
}
|
||||
int sourceflags2 = self->target != NULL ? self->target->flags2 : 0;
|
||||
|
||||
P_RadiusAttack (self, self->target, force, distance, self->DamageType, flags | RADF_NODAMAGE, fullthrustdistance);
|
||||
P_CheckSplash(self, distance << FRACBITS);
|
||||
|
|
@ -1104,7 +1105,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
|
|||
missile->FriendPlayer = 0;
|
||||
}
|
||||
}
|
||||
P_CheckMissileSpawn(missile);
|
||||
P_CheckMissileSpawn(missile, self->radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1128,6 +1129,7 @@ enum CBA_Flags
|
|||
CBAF_NORANDOM = 2,
|
||||
CBAF_EXPLICITANGLE = 4,
|
||||
CBAF_NOPITCH = 8,
|
||||
CBAF_NORANDOMPUFFZ = 16,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
|
||||
|
|
@ -1147,6 +1149,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
|
|||
int i;
|
||||
int bangle;
|
||||
int bslope = 0;
|
||||
int laflags = (flags & CBAF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0;
|
||||
|
||||
if (self->target || (flags & CBAF_AIMFACING))
|
||||
{
|
||||
|
|
@ -1177,7 +1180,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
|
|||
if (!(flags & CBAF_NORANDOM))
|
||||
damage *= ((pr_cabullet()%3)+1);
|
||||
|
||||
P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype);
|
||||
P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -1208,9 +1211,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMeleeAttack)
|
|||
{
|
||||
if (meleesound)
|
||||
S_Sound (self, CHAN_WEAPON, meleesound, 1, ATTN_NORM);
|
||||
P_DamageMobj (self->target, self, self, damage, damagetype);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, damagetype);
|
||||
if (bleed)
|
||||
P_TraceBleed (damage, self->target, self);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1245,9 +1248,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack)
|
|||
damagetype = NAME_Melee; // Melee is the default type
|
||||
if (meleesound)
|
||||
S_Sound (self, CHAN_WEAPON, meleesound, 1, ATTN_NORM);
|
||||
P_DamageMobj (self->target, self, self, damage, damagetype);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, damagetype);
|
||||
if (bleed)
|
||||
P_TraceBleed (damage, self->target, self);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
else if (ti)
|
||||
{
|
||||
|
|
@ -1263,7 +1266,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack)
|
|||
{
|
||||
missile->tracer = self->target;
|
||||
}
|
||||
P_CheckMissileSpawn(missile);
|
||||
P_CheckMissileSpawn(missile, self->radius);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -1303,6 +1306,7 @@ enum FB_Flags
|
|||
FBF_EXPLICITANGLE = 4,
|
||||
FBF_NOPITCH = 8,
|
||||
FBF_NOFLASH = 16,
|
||||
FBF_NORANDOMPUFFZ = 32,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
|
||||
|
|
@ -1324,6 +1328,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
|
|||
int i;
|
||||
int bangle;
|
||||
int bslope = 0;
|
||||
int laflags = (flags & FBF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0;
|
||||
|
||||
if ((flags & FBF_USEAMMO) && weapon)
|
||||
{
|
||||
|
|
@ -1342,7 +1347,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
|
|||
if (pufftype == NULL)
|
||||
pufftype = PClass::FindActor(NAME_BulletPuff);
|
||||
|
||||
S_Sound(self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
|
||||
if (weapon != NULL)
|
||||
{
|
||||
S_Sound(self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
if ((numbullets == 1 && !player->refire) || numbullets == 0)
|
||||
{
|
||||
|
|
@ -1351,7 +1359,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
|
|||
if (!(flags & FBF_NORANDOM))
|
||||
damage *= ((pr_cwbullet()%3)+1);
|
||||
|
||||
P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype);
|
||||
P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1378,7 +1386,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
|
|||
if (!(flags & FBF_NORANDOM))
|
||||
damage *= ((pr_cwbullet()%3)+1);
|
||||
|
||||
P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype);
|
||||
P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -1464,6 +1472,7 @@ enum
|
|||
CPF_USEAMMO = 1,
|
||||
CPF_DAGGER = 2,
|
||||
CPF_PULLIN = 4,
|
||||
CPF_NORANDOMPUFFZ = 8,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
|
||||
|
|
@ -1504,8 +1513,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
|
|||
|
||||
if (pufftype == NULL)
|
||||
pufftype = PClass::FindActor(NAME_BulletPuff);
|
||||
int puffFlags = LAF_ISMELEEATTACK | (flags & CPF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0;
|
||||
|
||||
P_LineAttack (self, angle, range, pitch, damage, NAME_Melee, pufftype, true, &linetarget);
|
||||
P_LineAttack (self, angle, range, pitch, damage, NAME_Melee, pufftype, puffFlags, &linetarget);
|
||||
|
||||
// turn to face target
|
||||
if (linetarget)
|
||||
|
|
@ -1513,7 +1523,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
|
|||
if (lifesteal)
|
||||
P_GiveBody (self, (damage * lifesteal) >> FRACBITS);
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
|
||||
if (weapon != NULL)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
self->angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y);
|
||||
|
||||
|
|
@ -1548,6 +1561,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
|
|||
PARAM_FLOAT_OPT (sparsity) { sparsity = 1; }
|
||||
PARAM_FLOAT_OPT (driftspeed) { driftspeed = 1; }
|
||||
PARAM_CLASS_OPT (spawnclass, AActor){ spawnclass = NULL; }
|
||||
PARAM_FIXED_OPT (spawnofs_z) { spawnofs_z = 0; }
|
||||
|
||||
if (range == 0) range = 8192*FRACUNIT;
|
||||
if (sparsity == 0) sparsity=1.0;
|
||||
|
|
@ -1578,7 +1592,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
|
|||
slope = pr_crailgun.Random2() * (spread_z / 255);
|
||||
}
|
||||
|
||||
P_RailAttack (self, damage, spawnofs_xy, color1, color2, maxdiff, flags, pufftype, angle, slope, range, duration, sparsity, driftspeed, spawnclass);
|
||||
P_RailAttack (self, damage, spawnofs_xy, spawnofs_z, color1, color2, maxdiff, flags, pufftype, angle, slope, range, duration, sparsity, driftspeed, spawnclass);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1613,6 +1627,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
|
|||
PARAM_FLOAT_OPT (sparsity) { sparsity = 1; }
|
||||
PARAM_FLOAT_OPT (driftspeed) { driftspeed = 1; }
|
||||
PARAM_CLASS_OPT (spawnclass, AActor){ spawnclass = NULL; }
|
||||
PARAM_FIXED_OPT (spawnofs_z) { spawnofs_z = 0; }
|
||||
|
||||
if (range == 0) range = 8192*FRACUNIT;
|
||||
if (sparsity == 0) sparsity = 1;
|
||||
|
|
@ -1696,7 +1711,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
|
|||
slopeoffset = pr_crailgun.Random2() * (spread_z / 255);
|
||||
}
|
||||
|
||||
P_RailAttack (self, damage, spawnofs_xy, color1, color2, maxdiff, flags, pufftype, angleoffset, slopeoffset, range, duration, sparsity, driftspeed, spawnclass);
|
||||
P_RailAttack (self, damage, spawnofs_xy, spawnofs_z, color1, color2, maxdiff, flags, pufftype, angleoffset, slopeoffset, range, duration, sparsity, driftspeed, spawnclass);
|
||||
|
||||
self->x = saved_x;
|
||||
self->y = saved_y;
|
||||
|
|
@ -1854,92 +1869,139 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromTarget)
|
|||
// Common code for A_SpawnItem and A_SpawnItemEx
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
enum SIX_Flags
|
||||
{
|
||||
SIXF_TRANSFERTRANSLATION=1,
|
||||
SIXF_ABSOLUTEPOSITION=2,
|
||||
SIXF_ABSOLUTEANGLE=4,
|
||||
SIXF_ABSOLUTEVELOCITY=8,
|
||||
SIXF_SETMASTER=16,
|
||||
SIXF_NOCHECKPOSITION=32,
|
||||
SIXF_TELEFRAG=64,
|
||||
// 128 is used by Skulltag!
|
||||
SIXF_TRANSFERAMBUSHFLAG=256,
|
||||
SIXF_TRANSFERPITCH=512,
|
||||
SIXF_TRANSFERPOINTERS=1024,
|
||||
SIXF_TRANSFERTRANSLATION = 1 << 0,
|
||||
SIXF_ABSOLUTEPOSITION = 1 << 1,
|
||||
SIXF_ABSOLUTEANGLE = 1 << 2,
|
||||
SIXF_ABSOLUTEVELOCITY = 1 << 3,
|
||||
SIXF_SETMASTER = 1 << 4,
|
||||
SIXF_NOCHECKPOSITION = 1 << 5,
|
||||
SIXF_TELEFRAG = 1 << 6,
|
||||
SIXF_CLIENTSIDE = 1 << 7, // only used by Skulldronum
|
||||
SIXF_TRANSFERAMBUSHFLAG = 1 << 8,
|
||||
SIXF_TRANSFERPITCH = 1 << 9,
|
||||
SIXF_TRANSFERPOINTERS = 1 << 10,
|
||||
SIXF_USEBLOODCOLOR = 1 << 11,
|
||||
SIXF_CLEARCALLERTID = 1 << 12,
|
||||
SIXF_MULTIPLYSPEED = 1 << 13,
|
||||
SIXF_TRANSFERSCALE = 1 << 14,
|
||||
SIXF_TRANSFERSPECIAL = 1 << 15,
|
||||
SIXF_CLEARCALLERSPECIAL = 1 << 16,
|
||||
};
|
||||
|
||||
|
||||
static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
||||
{
|
||||
if (mo)
|
||||
if (mo == NULL)
|
||||
{
|
||||
AActor * originator = self;
|
||||
return false;
|
||||
}
|
||||
AActor *originator = self;
|
||||
|
||||
if ((flags & SIXF_TRANSFERTRANSLATION) && !(mo->flags2 & MF2_DONTTRANSLATE))
|
||||
if (!(mo->flags2 & MF2_DONTTRANSLATE))
|
||||
{
|
||||
if (flags & SIXF_TRANSFERTRANSLATION)
|
||||
{
|
||||
mo->Translation = self->Translation;
|
||||
}
|
||||
if (flags & SIXF_TRANSFERPOINTERS)
|
||||
else if (flags & SIXF_USEBLOODCOLOR)
|
||||
{
|
||||
mo->target = self->target;
|
||||
mo->master = self->master; // This will be overridden later if SIXF_SETMASTER is set
|
||||
mo->tracer = self->tracer;
|
||||
// [XA] Use the spawning actor's BloodColor to translate the newly-spawned object.
|
||||
PalEntry bloodcolor = self->GetBloodColor();
|
||||
mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
||||
}
|
||||
}
|
||||
if (flags & SIXF_TRANSFERPOINTERS)
|
||||
{
|
||||
mo->target = self->target;
|
||||
mo->master = self->master; // This will be overridden later if SIXF_SETMASTER is set
|
||||
mo->tracer = self->tracer;
|
||||
}
|
||||
|
||||
mo->angle=self->angle;
|
||||
if (flags & SIXF_TRANSFERPITCH) mo->pitch = self->pitch;
|
||||
while (originator && originator->isMissile()) originator = originator->target;
|
||||
mo->angle = self->angle;
|
||||
if (flags & SIXF_TRANSFERPITCH)
|
||||
{
|
||||
mo->pitch = self->pitch;
|
||||
}
|
||||
while (originator && originator->isMissile())
|
||||
{
|
||||
originator = originator->target;
|
||||
}
|
||||
|
||||
if (flags & SIXF_TELEFRAG)
|
||||
if (flags & SIXF_TELEFRAG)
|
||||
{
|
||||
P_TeleportMove(mo, mo->x, mo->y, mo->z, true);
|
||||
// This is needed to ensure consistent behavior.
|
||||
// Otherwise it will only spawn if nothing gets telefragged
|
||||
flags |= SIXF_NOCHECKPOSITION;
|
||||
}
|
||||
if (mo->flags3 & MF3_ISMONSTER)
|
||||
{
|
||||
if (!(flags & SIXF_NOCHECKPOSITION) && !P_TestMobjLocation(mo))
|
||||
{
|
||||
P_TeleportMove(mo, mo->x, mo->y, mo->z, true);
|
||||
// This is needed to ensure consistent behavior.
|
||||
// Otherwise it will only spawn if nothing gets telefragged
|
||||
flags |= SIXF_NOCHECKPOSITION;
|
||||
// The monster is blocked so don't spawn it at all!
|
||||
mo->ClearCounters();
|
||||
mo->Destroy();
|
||||
return false;
|
||||
}
|
||||
if (mo->flags3&MF3_ISMONSTER)
|
||||
else if (originator)
|
||||
{
|
||||
if (!(flags&SIXF_NOCHECKPOSITION) && !P_TestMobjLocation(mo))
|
||||
if (originator->flags3 & MF3_ISMONSTER)
|
||||
{
|
||||
// The monster is blocked so don't spawn it at all!
|
||||
mo->ClearCounters();
|
||||
mo->Destroy();
|
||||
return false;
|
||||
// If this is a monster transfer all friendliness information
|
||||
mo->CopyFriendliness(originator, true);
|
||||
if (flags & SIXF_SETMASTER) mo->master = originator; // don't let it attack you (optional)!
|
||||
}
|
||||
else if (originator)
|
||||
else if (originator->player)
|
||||
{
|
||||
if (originator->flags3&MF3_ISMONSTER)
|
||||
{
|
||||
// If this is a monster transfer all friendliness information
|
||||
mo->CopyFriendliness(originator, true);
|
||||
if (flags&SIXF_SETMASTER) mo->master = originator; // don't let it attack you (optional)!
|
||||
}
|
||||
else if (originator->player)
|
||||
{
|
||||
// A player always spawns a monster friendly to him
|
||||
mo->flags |= MF_FRIENDLY;
|
||||
mo->SetFriendPlayer(originator->player);
|
||||
// A player always spawns a monster friendly to him
|
||||
mo->flags |= MF_FRIENDLY;
|
||||
mo->SetFriendPlayer(originator->player);
|
||||
|
||||
AActor * attacker=originator->player->attacker;
|
||||
if (attacker)
|
||||
AActor * attacker=originator->player->attacker;
|
||||
if (attacker)
|
||||
{
|
||||
if (!(attacker->flags&MF_FRIENDLY) ||
|
||||
(deathmatch && attacker->FriendPlayer!=0 && attacker->FriendPlayer!=mo->FriendPlayer))
|
||||
{
|
||||
if (!(attacker->flags&MF_FRIENDLY) ||
|
||||
(deathmatch && attacker->FriendPlayer!=0 && attacker->FriendPlayer!=mo->FriendPlayer))
|
||||
{
|
||||
// Target the monster which last attacked the player
|
||||
mo->LastHeard = mo->target = attacker;
|
||||
}
|
||||
// Target the monster which last attacked the player
|
||||
mo->LastHeard = mo->target = attacker;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!(flags & SIXF_TRANSFERPOINTERS))
|
||||
{
|
||||
// If this is a missile or something else set the target to the originator
|
||||
mo->target=originator? originator : self;
|
||||
}
|
||||
}
|
||||
else if (!(flags & SIXF_TRANSFERPOINTERS))
|
||||
{
|
||||
// If this is a missile or something else set the target to the originator
|
||||
mo->target = originator ? originator : self;
|
||||
}
|
||||
if (flags & SIXF_TRANSFERSCALE)
|
||||
{
|
||||
mo->scaleX = self->scaleX;
|
||||
mo->scaleY = self->scaleY;
|
||||
}
|
||||
if (flags & SIXF_TRANSFERAMBUSHFLAG)
|
||||
{
|
||||
mo->flags = (mo->flags & ~MF_AMBUSH) | (self->flags & MF_AMBUSH);
|
||||
}
|
||||
if (flags & SIXF_CLEARCALLERTID)
|
||||
{
|
||||
self->RemoveFromHash();
|
||||
self->tid = 0;
|
||||
}
|
||||
if (flags & SIXF_TRANSFERSPECIAL)
|
||||
{
|
||||
mo->special = self->special;
|
||||
memcpy(mo->args, self->args, sizeof(self->args));
|
||||
}
|
||||
if (flags & SIXF_CLEARCALLERSPECIAL)
|
||||
{
|
||||
self->special = 0;
|
||||
memset(self->args, 0, sizeof(self->args));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2021,6 +2083,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx)
|
|||
PARAM_ANGLE_OPT (angle) { angle = 0; }
|
||||
PARAM_INT_OPT (flags) { flags = 0; }
|
||||
PARAM_INT_OPT (chance) { chance = 0; }
|
||||
PARAM_INT_OPT (tid) { tid = 0; }
|
||||
|
||||
if (missile == NULL)
|
||||
{
|
||||
|
|
@ -2066,17 +2129,30 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx)
|
|||
xvel = newxvel;
|
||||
}
|
||||
|
||||
AActor * mo = Spawn(missile, x, y, self->z - self->floorclip + self->GetBobOffset() + zofs, ALLOW_REPLACE);
|
||||
AActor *mo = Spawn(missile, x, y, self->z - self->floorclip + self->GetBobOffset() + zofs, ALLOW_REPLACE);
|
||||
bool res = InitSpawnedItem(self, mo, flags);
|
||||
ACTION_SET_RESULT(res); // for an inventory item's use state
|
||||
if (mo)
|
||||
if (res)
|
||||
{
|
||||
mo->velx = xvel;
|
||||
mo->vely = yvel;
|
||||
mo->velz = zvel;
|
||||
if (tid != 0)
|
||||
{
|
||||
assert(mo->tid == 0);
|
||||
mo->tid = tid;
|
||||
mo->AddToHash();
|
||||
}
|
||||
if (flags & SIXF_MULTIPLYSPEED)
|
||||
{
|
||||
mo->velx = FixedMul(xvel, mo->Speed);
|
||||
mo->vely = FixedMul(yvel, mo->Speed);
|
||||
mo->velz = FixedMul(zvel, mo->Speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
mo->velx = xvel;
|
||||
mo->vely = yvel;
|
||||
mo->velz = zvel;
|
||||
}
|
||||
mo->angle = angle;
|
||||
if (flags & SIXF_TRANSFERAMBUSHFLAG)
|
||||
mo->flags = (mo->flags & ~MF_AMBUSH) | (self->flags & MF_AMBUSH);
|
||||
}
|
||||
return numret;
|
||||
}
|
||||
|
|
@ -2146,8 +2222,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade)
|
|||
bo->vely = xy_vely + z_vely + (self->vely >> 1);
|
||||
bo->velz = xy_velz + z_velz;
|
||||
|
||||
bo->target= self;
|
||||
P_CheckMissileSpawn (bo);
|
||||
bo->target = self;
|
||||
P_CheckMissileSpawn (bo, self->radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2476,15 +2552,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnDebris)
|
|||
for (i = 0; i < GetDefaultByType(debris)->health; i++)
|
||||
{
|
||||
mo = Spawn(debris, self->x+((pr_spawndebris()-128)<<12),
|
||||
self->y+((pr_spawndebris()-128)<<12),
|
||||
self->z+(pr_spawndebris()*self->height/256+self->GetBobOffset()), ALLOW_REPLACE);
|
||||
if (mo && transfer_translation)
|
||||
self->y + ((pr_spawndebris()-128)<<12),
|
||||
self->z + (pr_spawndebris()*self->height/256+self->GetBobOffset()), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->Translation = self->Translation;
|
||||
}
|
||||
if (mo && i < mo->GetClass()->NumOwnedStates)
|
||||
{
|
||||
mo->SetState (mo->GetClass()->OwnedStates + i);
|
||||
if (transfer_translation)
|
||||
{
|
||||
mo->Translation = self->Translation;
|
||||
}
|
||||
if (i < mo->GetClass()->NumOwnedStates)
|
||||
{
|
||||
mo->SetState (mo->GetClass()->OwnedStates + i);
|
||||
}
|
||||
mo->velz = FixedMul(mult_v, ((pr_spawndebris()&7)+5)*FRACUNIT);
|
||||
mo->velx = FixedMul(mult_h, pr_spawndebris.Random2()<<(FRACBITS-6));
|
||||
mo->vely = FixedMul(mult_h, pr_spawndebris.Random2()<<(FRACBITS-6));
|
||||
|
|
@ -2722,11 +2801,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
|
|||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
if (self->master != NULL)
|
||||
{
|
||||
if (mo->master == self->master && mo != self)
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR);
|
||||
if (mo->master == self->master && mo != self)
|
||||
{
|
||||
P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -3002,7 +3084,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayerSkinCheck)
|
|||
|
||||
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
|
||||
if (self->player != NULL &&
|
||||
skins[self->player->userinfo.skin].othergame)
|
||||
skins[self->player->userinfo.GetSkin()].othergame)
|
||||
{
|
||||
ACTION_JUMP(jump);
|
||||
}
|
||||
|
|
@ -3041,6 +3123,295 @@ DEFINE_ACTION_FUNCTION(AActor, A_ClearTarget)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_CheckLOF (state jump, int flags = CRF_AIM_VERT|CRF_AIM_HOR,
|
||||
// fixed range = 0, angle angle = 0, angle pitch = 0,
|
||||
// fixed offsetheight = 32, fixed offsetwidth = 0,
|
||||
// int ptr_target = AAPTR_DEFAULT (target) )
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
enum CLOF_flags
|
||||
{
|
||||
CLOFF_NOAIM_VERT = 0x1,
|
||||
CLOFF_NOAIM_HORZ = 0x2,
|
||||
|
||||
CLOFF_JUMPENEMY = 0x4,
|
||||
CLOFF_JUMPFRIEND = 0x8,
|
||||
CLOFF_JUMPOBJECT = 0x10,
|
||||
CLOFF_JUMPNONHOSTILE = 0x20,
|
||||
|
||||
CLOFF_SKIPENEMY = 0x40,
|
||||
CLOFF_SKIPFRIEND = 0x80,
|
||||
CLOFF_SKIPOBJECT = 0x100,
|
||||
CLOFF_SKIPNONHOSTILE = 0x200,
|
||||
|
||||
CLOFF_MUSTBESHOOTABLE = 0x400,
|
||||
|
||||
CLOFF_SKIPTARGET = 0x800,
|
||||
CLOFF_ALLOWNULL = 0x1000,
|
||||
CLOFF_CHECKPARTIAL = 0x2000,
|
||||
|
||||
CLOFF_MUSTBEGHOST = 0x4000,
|
||||
CLOFF_IGNOREGHOST = 0x8000,
|
||||
|
||||
CLOFF_MUSTBESOLID = 0x10000,
|
||||
CLOFF_BEYONDTARGET = 0x20000,
|
||||
|
||||
CLOFF_FROMBASE = 0x40000,
|
||||
CLOFF_MUL_HEIGHT = 0x80000,
|
||||
CLOFF_MUL_WIDTH = 0x100000,
|
||||
|
||||
CLOFF_JUMP_ON_MISS = 0x200000,
|
||||
CLOFF_AIM_VERT_NOOFFSET = 0x400000,
|
||||
};
|
||||
|
||||
struct LOFData
|
||||
{
|
||||
AActor *Self;
|
||||
AActor *Target;
|
||||
int Flags;
|
||||
bool BadActor;
|
||||
};
|
||||
|
||||
ETraceStatus CheckLOFTraceFunc(FTraceResults &trace, void *userdata)
|
||||
{
|
||||
LOFData *data = (LOFData *)userdata;
|
||||
int flags = data->Flags;
|
||||
|
||||
if (trace.HitType != TRACE_HitActor)
|
||||
{
|
||||
return TRACE_Stop;
|
||||
}
|
||||
if (trace.Actor == data->Target)
|
||||
{
|
||||
if (flags & CLOFF_SKIPTARGET)
|
||||
{
|
||||
if (flags & CLOFF_BEYONDTARGET)
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
return TRACE_Abort;
|
||||
}
|
||||
return TRACE_Stop;
|
||||
}
|
||||
if (flags & CLOFF_MUSTBESHOOTABLE)
|
||||
{ // all shootability checks go here
|
||||
if (!(trace.Actor->flags & MF_SHOOTABLE))
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
if (trace.Actor->flags2 & MF2_NONSHOOTABLE)
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
}
|
||||
if ((flags & CLOFF_MUSTBESOLID) && !(trace.Actor->flags & MF_SOLID))
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
if (flags & CLOFF_MUSTBEGHOST)
|
||||
{
|
||||
if (!(trace.Actor->flags3 & MF3_GHOST))
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
}
|
||||
else if (flags & CLOFF_IGNOREGHOST)
|
||||
{
|
||||
if (trace.Actor->flags3 & MF3_GHOST)
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
}
|
||||
if (
|
||||
((flags & CLOFF_JUMPENEMY) && data->Self->IsHostile(trace.Actor)) ||
|
||||
((flags & CLOFF_JUMPFRIEND) && data->Self->IsFriend(trace.Actor)) ||
|
||||
((flags & CLOFF_JUMPOBJECT) && !(trace.Actor->flags3 & MF3_ISMONSTER)) ||
|
||||
((flags & CLOFF_JUMPNONHOSTILE) && (trace.Actor->flags3 & MF3_ISMONSTER) && !data->Self->IsHostile(trace.Actor))
|
||||
)
|
||||
{
|
||||
return TRACE_Stop;
|
||||
}
|
||||
if (
|
||||
((flags & CLOFF_SKIPENEMY) && data->Self->IsHostile(trace.Actor)) ||
|
||||
((flags & CLOFF_SKIPFRIEND) && data->Self->IsFriend(trace.Actor)) ||
|
||||
((flags & CLOFF_SKIPOBJECT) && !(trace.Actor->flags3 & MF3_ISMONSTER)) ||
|
||||
((flags & CLOFF_SKIPNONHOSTILE) && (trace.Actor->flags3 & MF3_ISMONSTER) && !data->Self->IsHostile(trace.Actor))
|
||||
)
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
data->BadActor = true;
|
||||
return TRACE_Abort;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
|
||||
{
|
||||
// Check line of fire
|
||||
|
||||
/*
|
||||
Not accounted for / I don't know how it works: FLOORCLIP
|
||||
*/
|
||||
|
||||
AActor *target;
|
||||
fixed_t
|
||||
x1, y1, z1,
|
||||
vx, vy, vz;
|
||||
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_STATE (jump);
|
||||
PARAM_INT_OPT (flags) { flags = 0; }
|
||||
PARAM_FIXED_OPT (range) { range = 0; }
|
||||
PARAM_FIXED_OPT (minrange) { minrange = 0; }
|
||||
{
|
||||
PARAM_ANGLE_OPT (angle) { angle = 0; }
|
||||
PARAM_ANGLE_OPT (pitch) { pitch = 0; }
|
||||
PARAM_FIXED_OPT (offsetheight) { offsetheight = 0; }
|
||||
PARAM_FIXED_OPT (offsetwidth) { offsetwidth = 0; }
|
||||
PARAM_INT_OPT (ptr_target) { ptr_target = AAPTR_DEFAULT; }
|
||||
|
||||
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
|
||||
|
||||
target = COPY_AAPTR(self, ptr_target == AAPTR_DEFAULT ? AAPTR_TARGET|AAPTR_PLAYER_GETTARGET|AAPTR_NULL : ptr_target); // no player-support by default
|
||||
|
||||
if (flags & CLOFF_MUL_HEIGHT)
|
||||
{
|
||||
if (self->player != NULL)
|
||||
{
|
||||
// Synced with hitscan: self->player->mo->height is strangely conscientious about getting the right actor for player
|
||||
offsetheight = FixedMul(offsetheight, FixedMul (self->player->mo->height, self->player->crouchfactor));
|
||||
}
|
||||
else
|
||||
{
|
||||
offsetheight = FixedMul(offsetheight, self->height);
|
||||
}
|
||||
}
|
||||
if (flags & CLOFF_MUL_WIDTH)
|
||||
{
|
||||
offsetwidth = FixedMul(self->radius, offsetwidth);
|
||||
}
|
||||
|
||||
x1 = self->x;
|
||||
y1 = self->y;
|
||||
z1 = self->z + offsetheight - self->floorclip;
|
||||
|
||||
if (!(flags & CLOFF_FROMBASE))
|
||||
{ // default to hitscan origin
|
||||
|
||||
// Synced with hitscan: self->height is strangely NON-conscientious about getting the right actor for player
|
||||
z1 += (self->height >> 1);
|
||||
if (self->player != NULL)
|
||||
{
|
||||
z1 += FixedMul (self->player->mo->AttackZOffset, self->player->crouchfactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
z1 += 8*FRACUNIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (target)
|
||||
{
|
||||
FVector2 xyvec(target->x - x1, target->y - y1);
|
||||
fixed_t distance = P_AproxDistance((fixed_t)xyvec.Length(), target->z - z1);
|
||||
|
||||
if (range && !(flags & CLOFF_CHECKPARTIAL))
|
||||
{
|
||||
if (distance > range)
|
||||
return numret;
|
||||
}
|
||||
|
||||
{
|
||||
angle_t ang;
|
||||
|
||||
if (flags & CLOFF_NOAIM_HORZ)
|
||||
{
|
||||
ang = self->angle;
|
||||
}
|
||||
else ang = R_PointToAngle2 (x1, y1, target->x, target->y);
|
||||
|
||||
angle += ang;
|
||||
|
||||
ang >>= ANGLETOFINESHIFT;
|
||||
x1 += FixedMul(offsetwidth, finesine[ang]);
|
||||
y1 -= FixedMul(offsetwidth, finecosine[ang]);
|
||||
}
|
||||
|
||||
if (flags & CLOFF_NOAIM_VERT)
|
||||
{
|
||||
pitch += self->pitch;
|
||||
}
|
||||
else if (flags & CLOFF_AIM_VERT_NOOFFSET)
|
||||
{
|
||||
pitch += R_PointToAngle2 (0,0, (fixed_t)xyvec.Length(), target->z - z1 + offsetheight + target->height / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
pitch += R_PointToAngle2 (0,0, (fixed_t)xyvec.Length(), target->z - z1 + target->height / 2);
|
||||
}
|
||||
}
|
||||
else if (flags & CLOFF_ALLOWNULL)
|
||||
{
|
||||
angle += self->angle;
|
||||
pitch += self->pitch;
|
||||
|
||||
angle_t ang = self->angle >> ANGLETOFINESHIFT;
|
||||
x1 += FixedMul(offsetwidth, finesine[ang]);
|
||||
y1 -= FixedMul(offsetwidth, finecosine[ang]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return numret;
|
||||
}
|
||||
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
pitch = (0-pitch)>>ANGLETOFINESHIFT;
|
||||
|
||||
vx = FixedMul (finecosine[pitch], finecosine[angle]);
|
||||
vy = FixedMul (finecosine[pitch], finesine[angle]);
|
||||
vz = -finesine[pitch];
|
||||
}
|
||||
|
||||
/* Variable set:
|
||||
|
||||
jump, flags, target
|
||||
x1,y1,z1 (trace point of origin)
|
||||
vx,vy,vz (trace unit vector)
|
||||
range
|
||||
*/
|
||||
|
||||
sector_t *sec = P_PointInSector(x1, y1);
|
||||
|
||||
if (range == 0)
|
||||
{
|
||||
range = (self->player != NULL) ? PLAYERMISSILERANGE : MISSILERANGE;
|
||||
}
|
||||
|
||||
FTraceResults trace;
|
||||
LOFData lof_data;
|
||||
|
||||
lof_data.Self = self;
|
||||
lof_data.Target = target;
|
||||
lof_data.Flags = flags;
|
||||
lof_data.BadActor = false;
|
||||
|
||||
Trace(x1, y1, z1, sec, vx, vy, vz, range, 0xFFFFFFFF, ML_BLOCKEVERYTHING, self, trace, 0,
|
||||
CheckLOFTraceFunc, &lof_data);
|
||||
|
||||
if (trace.HitType == TRACE_HitActor ||
|
||||
((flags & CLOFF_JUMP_ON_MISS) && !lof_data.BadActor && trace.HitType != TRACE_HitNone))
|
||||
{
|
||||
if (minrange > 0 && trace.Distance < minrange)
|
||||
{
|
||||
return numret;
|
||||
}
|
||||
ACTION_JUMP(jump);
|
||||
}
|
||||
return numret;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_JumpIfTargetInLOS (state label, optional fixed fov, optional int flags,
|
||||
|
|
@ -3068,7 +3439,8 @@ enum JLOS_flags
|
|||
JLOSF_TARGETLOS=128,
|
||||
JLOSF_FLIPFOV=256,
|
||||
JLOSF_ALLYNOJUMP=512,
|
||||
JLOSF_COMBATANTONLY=1024
|
||||
JLOSF_COMBATANTONLY=1024,
|
||||
JLOSF_NOAUTOAIM=2048,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
|
||||
|
|
@ -3118,7 +3490,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
|
|||
else
|
||||
{
|
||||
// Does the player aim at something that can be shot?
|
||||
P_BulletSlope(self, &target);
|
||||
P_AimLineAttack(self, self->angle, MISSILERANGE, &target, (flags & JLOSF_NOAUTOAIM) ? ANGLE_1/2 : 0);
|
||||
|
||||
if (!target) return numret;
|
||||
|
||||
|
|
@ -3366,18 +3738,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
|
|||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
if (self->master != NULL)
|
||||
{
|
||||
if (mo->master == self->master && mo != self)
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
if (amount > 0)
|
||||
if (mo->master == self->master && mo != self)
|
||||
{
|
||||
P_DamageMobj(mo, self, self, amount, damagetype, DMG_NO_ARMOR);
|
||||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
amount = -amount;
|
||||
P_GiveBody(mo, amount);
|
||||
if (amount > 0)
|
||||
{
|
||||
P_DamageMobj(mo, self, self, amount, damagetype, DMG_NO_ARMOR);
|
||||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
amount = -amount;
|
||||
P_GiveBody(mo, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3495,14 +3870,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag)
|
|||
bool linkchange = flagp == &self->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR);
|
||||
|
||||
if (linkchange) self->UnlinkFromWorld();
|
||||
if (value)
|
||||
{
|
||||
*flagp |= fd->flagbit;
|
||||
}
|
||||
else
|
||||
{
|
||||
*flagp &= ~fd->flagbit;
|
||||
}
|
||||
ModActorFlag(self, fd, value);
|
||||
if (linkchange) self->LinkToWorld();
|
||||
}
|
||||
kill_after = self->CountsAsKill();
|
||||
|
|
@ -3590,14 +3958,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag)
|
|||
|
||||
if (fd != NULL)
|
||||
{
|
||||
if (fd->structoffset == -1)
|
||||
{
|
||||
if (CheckDeprecatedFlags(owner, cls, fd->flagbit))
|
||||
{
|
||||
ACTION_JUMP(jumpto);
|
||||
}
|
||||
}
|
||||
else if (fd->flagbit & *(DWORD*)(((char*)owner) + fd->structoffset))
|
||||
if (CheckActorFlag(owner, fd))
|
||||
{
|
||||
ACTION_JUMP(jumpto);
|
||||
}
|
||||
|
|
@ -3638,9 +3999,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren)
|
|||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
while ((mo = it.Next()) != NULL)
|
||||
{
|
||||
if ( ( mo->master == self ) && ( ( mo->health <= 0 ) || removeall) )
|
||||
if (mo->master == self && (mo->health <= 0 || removeall))
|
||||
{
|
||||
P_RemoveThing(mo);
|
||||
}
|
||||
|
|
@ -3661,11 +4022,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings)
|
|||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
if (self->master != NULL)
|
||||
{
|
||||
if ( ( mo->master == self->master ) && ( mo != self ) && ( ( mo->health <= 0 ) || removeall) )
|
||||
while ((mo = it.Next()) != NULL)
|
||||
{
|
||||
P_RemoveThing(mo);
|
||||
if (mo->master == self->master && mo != self && (mo->health <= 0 || removeall))
|
||||
{
|
||||
P_RemoveThing(mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -3698,9 +4062,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren)
|
|||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
while ((mo = it.Next()))
|
||||
while ((mo = it.Next()) != NULL)
|
||||
{
|
||||
if ( mo->master == self )
|
||||
if (mo->master == self)
|
||||
{
|
||||
P_Thing_Raise(mo);
|
||||
}
|
||||
|
|
@ -3720,11 +4084,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings)
|
|||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
if (self->master != NULL)
|
||||
{
|
||||
if ( ( mo->master == self->master ) && ( mo != self ) )
|
||||
while ((mo = it.Next()) != NULL)
|
||||
{
|
||||
P_Thing_Raise(mo);
|
||||
if (mo->master == self->master && mo != self)
|
||||
{
|
||||
P_Thing_Raise(mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -4323,11 +4690,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
|
|||
damage >>= 2;
|
||||
if (damage)
|
||||
{
|
||||
P_DamageMobj(self->target, self, self, damage, mod, DMG_THRUSTLESS);
|
||||
int newdam = P_DamageMobj(self->target, self, self, damage, mod, DMG_THRUSTLESS);
|
||||
if (spawnblood)
|
||||
{
|
||||
P_SpawnBlood(dx, dy, dz, angle, damage, self->target);
|
||||
P_TraceBleed(damage, self->target, R_PointToAngle2(self->x, self->y, dx, dy), 0);
|
||||
P_SpawnBlood(dx, dy, dz, angle, newdam > 0 ? newdam : damage, self->target);
|
||||
P_TraceBleed(newdam > 0 ? newdam : damage, self->target, R_PointToAngle2(self->x, self->y, dx, dy), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4768,4 +5135,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics)
|
|||
|
||||
self->tics = tics_to_set;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_SetDamageType
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetDamageType)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_NAME(damagetype);
|
||||
|
||||
self->DamageType = damagetype;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue