- scriptified A_CustomPunch

This commit is contained in:
Christoph Oelckers 2018-11-24 14:48:30 +01:00
parent 7bb3855439
commit 5c130737c4
6 changed files with 146 additions and 184 deletions

View file

@ -1626,122 +1626,6 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_JumpIfNoAmmo)
//==========================================================================
//
// A_CustomPunch
//
// Berserk is not handled here. That can be done with A_CheckIfInventory
//
//==========================================================================
enum
{
CPF_USEAMMO = 1,
CPF_DAGGER = 2,
CPF_PULLIN = 4,
CPF_NORANDOMPUFFZ = 8,
CPF_NOTURN = 16,
CPF_STEALARMOR = 32,
};
DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch)
{
PARAM_ACTION_PROLOGUE(AStateProvider);
PARAM_INT (damage);
PARAM_BOOL (norandom);
PARAM_INT (flags);
PARAM_CLASS (pufftype, AActor);
PARAM_FLOAT (range);
PARAM_FLOAT (lifesteal);
PARAM_INT (lifestealmax);
PARAM_CLASS (armorbonustype, AActor);
PARAM_SOUND (MeleeSound);
PARAM_SOUND (MissSound);
if (!self->player)
return 0;
player_t *player = self->player;
AWeapon *weapon = player->ReadyWeapon;
DAngle angle;
DAngle pitch;
FTranslatedLineTarget t;
int actualdamage;
if (!norandom)
damage *= pr_cwpunch() % 8 + 1;
angle = self->Angles.Yaw + pr_cwpunch.Random2() * (5.625 / 256);
if (range == 0) range = DEFMELEERANGE;
pitch = P_AimLineAttack (self, angle, range, &t, 0., ALF_CHECK3D);
// only use ammo when actually hitting something!
if ((flags & CPF_USEAMMO) && t.linetarget && weapon && ACTION_CALL_FROM_PSPRITE())
{
if (!weapon->DepleteAmmo(weapon->bAltFire, true))
return 0; // out of ammo
}
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, puffFlags, &t, &actualdamage);
if (!t.linetarget)
{
if (MissSound) S_Sound(self, CHAN_WEAPON, MissSound, 1, ATTN_NORM);
}
else
{
if (lifesteal > 0 && !(t.linetarget->flags5 & MF5_DONTDRAIN))
{
if (flags & CPF_STEALARMOR)
{
if (armorbonustype == NULL)
{
armorbonustype = PClass::FindActor("ArmorBonus");
}
if (armorbonustype != NULL)
{
auto armorbonus = Spawn(armorbonustype);
armorbonus->IntVar(NAME_SaveAmount) *= int(actualdamage * lifesteal);
if (lifestealmax > 0) armorbonus->IntVar("MaxSaveAmount") = lifestealmax;
armorbonus->flags |= MF_DROPPED;
armorbonus->ClearCounters();
if (!static_cast<AInventory*>(armorbonus)->CallTryPickup(self))
{
armorbonus->Destroy ();
}
}
}
else
{
P_GiveBody (self, int(actualdamage * lifesteal), lifestealmax);
}
}
if (weapon != NULL)
{
if (MeleeSound) S_Sound(self, CHAN_WEAPON, MeleeSound, 1, ATTN_NORM);
else S_Sound (self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
}
if (!(flags & CPF_NOTURN))
{
// turn to face target
self->Angles.Yaw = t.angleFromSource;
}
if (flags & CPF_PULLIN) self->flags |= MF_JUSTATTACKED;
if (flags & CPF_DAGGER) P_DaggerAlert (self, t.linetarget);
}
return 0;
}
//==========================================================================
//
// customizable railgun attack function

View file

@ -268,71 +268,6 @@ DEFINE_ACTION_FUNCTION(AActor, SoundAlert)
return 0;
}
//============================================================================
//
// P_DaggerAlert
//
//============================================================================
void P_DaggerAlert(AActor *target, AActor *emitter)
{
AActor *looker;
sector_t *sec = emitter->Sector;
if (emitter->LastHeard != NULL)
return;
if (emitter->health <= 0)
return;
if (!(emitter->flags3 & MF3_ISMONSTER))
return;
if (emitter->flags4 & MF4_INCOMBAT)
return;
emitter->flags4 |= MF4_INCOMBAT;
emitter->target = target;
FState *painstate = emitter->FindState(NAME_Pain, NAME_Dagger);
if (painstate != NULL)
{
emitter->SetState(painstate);
}
for (looker = sec->thinglist; looker != NULL; looker = looker->snext)
{
if (looker == emitter || looker == target)
continue;
if (looker->health <= 0)
continue;
if (!(looker->flags4 & MF4_SEESDAGGERS))
continue;
if (!(looker->flags4 & MF4_INCOMBAT))
{
if (!P_CheckSight(looker, target) && !P_CheckSight(looker, emitter))
continue;
looker->target = target;
if (looker->SeeSound)
{
S_Sound(looker, CHAN_VOICE, looker->SeeSound, 1, ATTN_NORM);
}
looker->SetState(looker->SeeState);
looker->flags4 |= MF4_INCOMBAT;
}
}
}
DEFINE_ACTION_FUNCTION(AActor, DaggerAlert)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT(target, AActor);
// Note that the emitter is self, not the target of the alert! Target can be NULL.
P_DaggerAlert(target, self);
return 0;
}
//----------------------------------------------------------------------------
//
// AActor :: CheckMeleeRange

View file

@ -46,7 +46,6 @@ struct FLookExParams
FState *seestate;
};
void P_DaggerAlert (AActor *target, AActor *emitter);
bool P_HitFriend (AActor *self);
void P_NoiseAlert (AActor *target, AActor *emmiter, bool splash=false, double maxdist=0);

View file

@ -584,7 +584,6 @@ class Actor : Thinker native
native clearscope int PlayerNumber() const;
native void SetFriendPlayer(PlayerInfo player);
native void SoundAlert(Actor target, bool splash = false, double maxdist = 0);
native void DaggerAlert(Actor target);
native void ClearBounce();
native TerrainDef GetFloorTerrain();
native bool CheckLocalView(int consoleplayer);

View file

@ -116,5 +116,59 @@ extend class Actor
}
}
//============================================================================
//
// P_DaggerAlert
//
//============================================================================
void DaggerAlert(Actor target)
{
Actor looker;
if (LastHeard != NULL)
return;
if (health <= 0)
return;
if (!bIsMonster)
return;
if (bInCombat)
return;
bInCombat = true;
self.target = target;
let painstate = FindState('Pain', 'Dagger');
if (painstate != NULL)
{
SetState(painstate);
}
for (looker = cursector.thinglist; looker != NULL; looker = looker.snext)
{
if (looker == self || looker == target)
continue;
if (looker.health <= 0)
continue;
if (!looker.bSeesDaggers)
continue;
if (!looker.bInCombat)
{
if (!looker.CheckSight(target) && !looker.CheckSight(self))
continue;
looker.target = target;
if (looker.SeeSound)
{
looker.A_PlaySound(looker.SeeSound, CHAN_VOICE);
}
looker.SetState(looker.SeeState);
looker.bInCombat = true;
}
}
}
}

View file

@ -2,7 +2,6 @@
class StateProvider : Inventory native
{
action native state A_JumpIfNoAmmo(statelabel label);
action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "");
action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class<Actor> pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class<Actor> spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
action native void A_WeaponReady(int flags = 0);
@ -175,6 +174,98 @@ class StateProvider : Inventory native
return null;
}
//==========================================================================
//
// A_CustomPunch
//
// Berserk is not handled here. That can be done with A_CheckIfInventory
//
//==========================================================================
action void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "")
{
let player = self.player;
if (!player) return;
let weapon = player.ReadyWeapon;
double angle;
double pitch;
FTranslatedLineTarget t;
int actualdamage;
if (!norandom)
damage *= random[cwpunch](1, 8);
angle = self.Angle + random2[cwpunch]() * (5.625 / 256);
if (range == 0) range = DEFMELEERANGE;
pitch = AimLineAttack (angle, range, t, 0., ALF_CHECK3D);
// only use ammo when actually hitting something!
if ((flags & CPF_USEAMMO) && t.linetarget && weapon && stateinfo != null && stateinfo.mStateType == STATE_Psprite)
{
if (!weapon.DepleteAmmo(weapon.bAltFire, true))
return; // out of ammo
}
if (pufftype == NULL)
pufftype = 'BulletPuff';
int puffFlags = LAF_ISMELEEATTACK | ((flags & CPF_NORANDOMPUFFZ) ? LAF_NORANDOMPUFFZ : 0);
Actor puff;
[puff, actualdamage] = LineAttack (angle, range, pitch, damage, 'Melee', pufftype, puffFlags, t);
if (!t.linetarget)
{
if (MissSound) A_PlaySound(MissSound, CHAN_WEAPON);
}
else
{
if (lifesteal > 0 && !(t.linetarget.bDontDrain))
{
if (flags & CPF_STEALARMOR)
{
if (armorbonustype == NULL)
{
armorbonustype = 'ArmorBonus';
}
if (armorbonustype != NULL)
{
let armorbonus = ArmorBonus(Spawn(armorbonustype));
armorbonus.SaveAmount *= int(actualdamage * lifesteal);
if (lifestealmax > 0) armorbonus.MaxSaveAmount = lifestealmax;
armorbonus.bDropped = true;
armorbonus.ClearCounters();
if (!armorbonus.CallTryPickup(self))
{
armorbonus.Destroy ();
}
}
}
else
{
GiveBody (int(actualdamage * lifesteal), lifestealmax);
}
}
if (weapon != NULL)
{
if (MeleeSound) A_PlaySound(MeleeSound, CHAN_WEAPON);
else A_PlaySound(AttackSound, CHAN_WEAPON);
}
if (!(flags & CPF_NOTURN))
{
// turn to face target
self.Angle = t.angleFromSource;
}
if (flags & CPF_PULLIN) self.bJustAttacked = true;
if (flags & CPF_DAGGER) t.linetarget.DaggerAlert (self);
}
}
//---------------------------------------------------------------------------
//