- scriptified A_FireBullets and A_CustomBulletAttack.

This commit is contained in:
Christoph Oelckers 2018-11-24 13:50:27 +01:00
commit e071be8371
5 changed files with 234 additions and 280 deletions

View file

@ -75,7 +75,6 @@ AActor *SingleActorFromTID(int tid, AActor *defactor);
static FRandom pr_camissile ("CustomActorfire");
static FRandom pr_cabullet ("CustomBullet");
static FRandom pr_cwbullet ("CustomWpBullet");
static FRandom pr_cwjump ("CustomWpJump");
static FRandom pr_cwpunch ("CustomWpPunch");
static FRandom pr_grenade ("ThrowGrenade");
@ -1516,112 +1515,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnProjectile)
ACTION_RETURN_OBJECT(missile);
}
//==========================================================================
//
// An even more customizable hitscan attack
//
//==========================================================================
enum CBA_Flags
{
CBAF_AIMFACING = 1,
CBAF_NORANDOM = 2,
CBAF_EXPLICITANGLE = 4,
CBAF_NOPITCH = 8,
CBAF_NORANDOMPUFFZ = 16,
CBAF_PUFFTARGET = 32,
CBAF_PUFFMASTER = 64,
CBAF_PUFFTRACER = 128,
};
static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, bool cba);
DEFINE_ACTION_FUNCTION(AActor, A_CustomBulletAttack)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_ANGLE (spread_xy);
PARAM_ANGLE (spread_z);
PARAM_INT (numbullets);
PARAM_INT (damageperbullet);
PARAM_CLASS (pufftype, AActor);
PARAM_FLOAT (range);
PARAM_INT (flags);
PARAM_INT (ptr);
PARAM_CLASS (missile, AActor);
PARAM_FLOAT (Spawnheight);
PARAM_FLOAT (Spawnofs_xy);
AActor *ref = COPY_AAPTR(self, ptr);
if (range == 0)
range = MISSILERANGE;
int i;
DAngle bangle;
DAngle bslope = 0.;
int laflags = (flags & CBAF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0;
if (ref != NULL || (flags & CBAF_AIMFACING))
{
if (!(flags & CBAF_AIMFACING))
{
A_Face(self, ref);
}
bangle = self->Angles.Yaw;
if (!(flags & CBAF_NOPITCH)) bslope = P_AimLineAttack (self, bangle, MISSILERANGE);
if (pufftype == nullptr) pufftype = PClass::FindActor(NAME_BulletPuff);
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
for (i = 0; i < numbullets; i++)
{
DAngle angle = bangle;
DAngle slope = bslope;
if (flags & CBAF_EXPLICITANGLE)
{
angle += spread_xy;
slope += spread_z;
}
else
{
angle += spread_xy * (pr_cwbullet.Random2() / 255.);
slope += spread_z * (pr_cwbullet.Random2() / 255.);
}
int damage = damageperbullet;
if (!(flags & CBAF_NORANDOM))
damage *= ((pr_cabullet()%3)+1);
AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags);
if (missile != nullptr && pufftype != nullptr)
{
double x = Spawnofs_xy * angle.Cos();
double y = Spawnofs_xy * angle.Sin();
DVector3 pos = self->Pos();
self->SetXYZ(self->Vec3Offset(x, y, 0.));
AActor *proj = P_SpawnMissileAngleZSpeed(self, self->Z() + self->GetBobOffset() + Spawnheight, missile, self->Angles.Yaw, 0, GetDefaultByType(missile)->Speed, self, false);
self->SetXYZ(pos);
if (proj)
{
bool temp = (puff == nullptr);
if (!puff)
{
puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT);
}
if (puff)
{
AimBulletMissile(proj, puff, flags, temp, true);
}
}
}
}
}
return 0;
}
//==========================================================================
//
// A fully customizable melee attack
@ -1732,177 +1625,6 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_JumpIfNoAmmo)
}
//==========================================================================
//
// An even more customizable hitscan attack
//
//==========================================================================
enum FB_Flags
{
FBF_USEAMMO = 1,
FBF_NORANDOM = 2,
FBF_EXPLICITANGLE = 4,
FBF_NOPITCH = 8,
FBF_NOFLASH = 16,
FBF_NORANDOMPUFFZ = 32,
FBF_PUFFTARGET = 64,
FBF_PUFFMASTER = 128,
FBF_PUFFTRACER = 256,
};
static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, bool cba)
{
if (proj && puff)
{
if (proj)
{
// FAF_BOTTOM = 1
// Aim for the base of the puff as that's where blood puffs will spawn... roughly.
A_Face(proj, puff, 0., 0., 0., 0., 1);
proj->Vel3DFromAngle(proj->Angles.Pitch, proj->Speed);
if (!temp)
{
if (cba)
{
if (flags & CBAF_PUFFTARGET) proj->target = puff;
if (flags & CBAF_PUFFMASTER) proj->master = puff;
if (flags & CBAF_PUFFTRACER) proj->tracer = puff;
}
else
{
if (flags & FBF_PUFFTARGET) proj->target = puff;
if (flags & FBF_PUFFMASTER) proj->master = puff;
if (flags & FBF_PUFFTRACER) proj->tracer = puff;
}
}
}
}
if (puff && temp)
{
puff->Destroy();
}
}
DEFINE_ACTION_FUNCTION(AStateProvider, A_FireBullets)
{
PARAM_ACTION_PROLOGUE(AStateProvider);
PARAM_ANGLE (spread_xy);
PARAM_ANGLE (spread_z);
PARAM_INT (numbullets);
PARAM_INT (damageperbullet);
PARAM_CLASS (pufftype, AActor);
PARAM_INT (flags);
PARAM_FLOAT (range);
PARAM_CLASS (missile, AActor);
PARAM_FLOAT (Spawnheight);
PARAM_FLOAT (Spawnofs_xy);
if (!self->player) return 0;
player_t *player = self->player;
AWeapon *weapon = player->ReadyWeapon;
int i;
DAngle bangle;
DAngle bslope = 0.;
int laflags = (flags & FBF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0;
if ((flags & FBF_USEAMMO) && weapon && ACTION_CALL_FROM_PSPRITE())
{
if (!weapon->DepleteAmmo(weapon->bAltFire, true))
return 0; // out of ammo
}
if (range == 0) range = PLAYERMISSILERANGE;
if (!(flags & FBF_NOFLASH)) static_cast<APlayerPawn *>(self)->PlayAttacking2 ();
if (!(flags & FBF_NOPITCH)) bslope = P_BulletSlope(self);
bangle = self->Angles.Yaw;
if (pufftype == NULL) pufftype = PClass::FindActor(NAME_BulletPuff);
if (weapon != NULL)
{
S_Sound(self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
}
if ((numbullets == 1 && !player->refire) || numbullets == 0)
{
int damage = damageperbullet;
if (!(flags & FBF_NORANDOM))
damage *= ((pr_cwbullet()%3)+1);
AActor *puff = P_LineAttack(self, bangle, range, bslope, damage, NAME_Hitscan, pufftype, laflags);
if (missile != nullptr)
{
bool temp = false;
DAngle ang = self->Angles.Yaw - 90;
DVector2 ofs = ang.ToVector(Spawnofs_xy);
AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, bangle, nullptr, nullptr, false, true);
if (proj)
{
if (!puff)
{
temp = true;
puff = P_LineAttack(self, bangle, range, bslope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT);
}
AimBulletMissile(proj, puff, flags, temp, false);
}
}
}
else
{
if (numbullets < 0)
numbullets = 1;
for (i = 0; i < numbullets; i++)
{
DAngle angle = bangle;
DAngle slope = bslope;
if (flags & FBF_EXPLICITANGLE)
{
angle += spread_xy;
slope += spread_z;
}
else
{
angle += spread_xy * (pr_cwbullet.Random2() / 255.);
slope += spread_z * (pr_cwbullet.Random2() / 255.);
}
int damage = damageperbullet;
if (!(flags & FBF_NORANDOM))
damage *= ((pr_cwbullet()%3)+1);
AActor *puff = P_LineAttack(self, angle, range, slope, damage, NAME_Hitscan, pufftype, laflags);
if (missile != nullptr)
{
bool temp = false;
DAngle ang = self->Angles.Yaw - 90;
DVector2 ofs = ang.ToVector(Spawnofs_xy);
AActor *proj = P_SpawnPlayerMissile(self, ofs.X, ofs.Y, Spawnheight, missile, angle, nullptr, nullptr, false, true);
if (proj)
{
if (!puff)
{
temp = true;
puff = P_LineAttack(self, angle, range, slope, 0, NAME_Hitscan, pufftype, laflags | LAF_NOINTERACT);
}
AimBulletMissile(proj, puff, flags, temp, false);
}
}
}
}
return 0;
}
//==========================================================================
//