2008-09-15 14:11:05 +00:00
|
|
|
/*
|
2006-02-24 04:48:15 +00:00
|
|
|
#include "actor.h"
|
|
|
|
#include "p_enemy.h"
|
|
|
|
#include "a_action.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "a_doomglobal.h"
|
|
|
|
#include "s_sound.h"
|
2011-07-06 08:50:15 +00:00
|
|
|
#include "r_data/r_translate.h"
|
2008-08-05 13:50:57 +00:00
|
|
|
#include "thingdef/thingdef.h"
|
2008-09-14 23:54:38 +00:00
|
|
|
#include "g_level.h"
|
2008-09-15 14:11:05 +00:00
|
|
|
*/
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
#define MARINE_PAIN_CHANCE 160
|
|
|
|
|
|
|
|
static FRandom pr_m_refire ("SMarineRefire");
|
|
|
|
static FRandom pr_m_punch ("SMarinePunch");
|
|
|
|
static FRandom pr_m_gunshot ("SMarineGunshot");
|
|
|
|
static FRandom pr_m_saw ("SMarineSaw");
|
|
|
|
static FRandom pr_m_fireshotgun2 ("SMarineFireSSG");
|
|
|
|
|
2008-08-05 13:50:57 +00:00
|
|
|
IMPLEMENT_CLASS (AScriptedMarine)
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
void AScriptedMarine::Serialize (FArchive &arc)
|
|
|
|
{
|
|
|
|
Super::Serialize (arc);
|
|
|
|
|
|
|
|
if (arc.IsStoring ())
|
|
|
|
{
|
|
|
|
arc.WriteSprite (SpriteOverride);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SpriteOverride = arc.ReadSprite ();
|
|
|
|
}
|
2008-08-05 13:50:57 +00:00
|
|
|
arc << CurrentWeapon;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AScriptedMarine::Activate (AActor *activator)
|
|
|
|
{
|
|
|
|
if (flags2 & MF2_DORMANT)
|
|
|
|
{
|
|
|
|
flags2 &= ~MF2_DORMANT;
|
|
|
|
tics = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AScriptedMarine::Deactivate (AActor *activator)
|
|
|
|
{
|
|
|
|
if (!(flags2 & MF2_DORMANT))
|
|
|
|
{
|
|
|
|
flags2 |= MF2_DORMANT;
|
|
|
|
tics = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-05 13:50:57 +00:00
|
|
|
bool AScriptedMarine::GetWeaponStates(int weap, FState *&melee, FState *&missile)
|
|
|
|
{
|
|
|
|
static ENamedName WeaponNames[] =
|
|
|
|
{
|
|
|
|
NAME_None,
|
|
|
|
NAME_Fist,
|
|
|
|
NAME_Berserk,
|
|
|
|
NAME_Chainsaw,
|
|
|
|
NAME_Pistol,
|
|
|
|
NAME_Shotgun,
|
|
|
|
NAME_SSG,
|
|
|
|
NAME_Chaingun,
|
|
|
|
NAME_Rocket,
|
|
|
|
NAME_Plasma,
|
|
|
|
NAME_Railgun,
|
|
|
|
NAME_BFG
|
|
|
|
};
|
|
|
|
|
|
|
|
if (weap < WEAPON_Dummy || weap > WEAPON_BFG) weap = WEAPON_Dummy;
|
|
|
|
|
|
|
|
melee = FindState(NAME_Melee, WeaponNames[weap], true);
|
|
|
|
missile = FindState(NAME_Missile, WeaponNames[weap], true);
|
|
|
|
|
|
|
|
return melee != NULL || missile != NULL;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
void AScriptedMarine::BeginPlay ()
|
|
|
|
{
|
|
|
|
Super::BeginPlay ();
|
|
|
|
|
2008-08-05 13:50:57 +00:00
|
|
|
// Set the current weapon
|
|
|
|
for(int i=WEAPON_Dummy; i<=WEAPON_BFG; i++)
|
|
|
|
{
|
|
|
|
FState *melee, *missile;
|
|
|
|
if (GetWeaponStates(i, melee, missile))
|
|
|
|
{
|
|
|
|
if (melee == MeleeState && missile == MissileState)
|
|
|
|
{
|
|
|
|
CurrentWeapon = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AScriptedMarine::Tick ()
|
|
|
|
{
|
|
|
|
Super::Tick ();
|
|
|
|
|
|
|
|
// Override the standard sprite, if desired
|
2010-01-18 20:15:04 +00:00
|
|
|
if (SpriteOverride != 0 && sprite == SpawnState->sprite)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
sprite = SpriteOverride;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (special1 != 0)
|
|
|
|
{
|
2008-08-05 13:50:57 +00:00
|
|
|
if (CurrentWeapon == WEAPON_SuperShotgun)
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // Play SSG reload sounds
|
|
|
|
int ticks = level.maptime - special1;
|
|
|
|
if (ticks < 47)
|
|
|
|
{
|
|
|
|
switch (ticks)
|
|
|
|
{
|
|
|
|
case 14:
|
|
|
|
S_Sound (this, CHAN_WEAPON, "weapons/sshoto", 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
case 28:
|
|
|
|
S_Sound (this, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
case 41:
|
|
|
|
S_Sound (this, CHAN_WEAPON, "weapons/sshotc", 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
special1 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Wait for a long refire time
|
|
|
|
if (level.maptime >= special1)
|
|
|
|
{
|
|
|
|
special1 = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
flags |= MF_JUSTATTACKED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_Refire
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_Refire)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->target == NULL || self->target->health <= 0)
|
|
|
|
{
|
|
|
|
if (self->MissileState && pr_m_refire() < 160)
|
|
|
|
{ // Look for a new target most of the time
|
2009-09-16 15:54:04 +00:00
|
|
|
if (P_LookForPlayers (self, true, NULL) && P_CheckMissileRange (self))
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // Found somebody new and in range, so don't stop shooting
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
self->SetState (self->state + 1);
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
if ((self->MissileState == NULL && !self->CheckMeleeRange ()) ||
|
|
|
|
!P_CheckSight (self, self->target) ||
|
|
|
|
pr_m_refire() < 4) // Small chance of stopping even when target not dead
|
|
|
|
{
|
|
|
|
self->SetState (self->state + 1);
|
|
|
|
}
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_SawRefire
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_SawRefire)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->target == NULL || self->target->health <= 0)
|
|
|
|
{
|
|
|
|
self->SetState (self->state + 1);
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
if (!self->CheckMeleeRange ())
|
|
|
|
{
|
|
|
|
self->SetState (self->state + 1);
|
|
|
|
}
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
2008-08-05 13:50:57 +00:00
|
|
|
// A_MarineNoise
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_MarineNoise)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2008-08-05 13:50:57 +00:00
|
|
|
if (static_cast<AScriptedMarine *>(self)->CurrentWeapon == AScriptedMarine::WEAPON_Chainsaw)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
S_Sound (self, CHAN_WEAPON, "weapons/sawidle", 1, ATTN_NORM);
|
|
|
|
}
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
2008-08-05 13:50:57 +00:00
|
|
|
// A_MarineChase
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_MarineChase)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
2008-08-10 22:48:37 +00:00
|
|
|
CALL_ACTION(A_MarineNoise, self);
|
2010-02-12 06:04:57 +00:00
|
|
|
A_Chase (stack, self);
|
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
2008-08-05 13:50:57 +00:00
|
|
|
// A_MarineLook
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_MarineLook)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
2008-08-10 22:48:37 +00:00
|
|
|
CALL_ACTION(A_MarineNoise, self);
|
|
|
|
CALL_ACTION(A_Look, self);
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_Saw
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2009-06-27 19:37:53 +00:00
|
|
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; }
|
|
|
|
PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; }
|
|
|
|
PARAM_INT_OPT (damage) { damage = 2; }
|
|
|
|
PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; }
|
2009-06-27 19:37:53 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2010-03-24 02:49:37 +00:00
|
|
|
if (pufftype == NULL)
|
|
|
|
{
|
|
|
|
pufftype = PClass::FindActor(NAME_BulletPuff);
|
|
|
|
}
|
|
|
|
if (damage == 0)
|
|
|
|
{
|
|
|
|
damage = 2;
|
|
|
|
}
|
2009-06-27 19:37:53 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
A_FaceTarget (self);
|
|
|
|
if (self->CheckMeleeRange ())
|
|
|
|
{
|
|
|
|
angle_t angle;
|
2008-04-10 14:38:43 +00:00
|
|
|
AActor *linetarget;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-06-27 19:37:53 +00:00
|
|
|
damage *= (pr_m_saw()%10+1);
|
2006-02-24 04:48:15 +00:00
|
|
|
angle = self->angle + (pr_m_saw.Random2() << 18);
|
|
|
|
|
|
|
|
P_LineAttack (self, angle, MELEERANGE+1,
|
2008-04-10 14:38:43 +00:00
|
|
|
P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage,
|
2010-06-13 11:14:01 +00:00
|
|
|
NAME_Melee, pufftype, false, &linetarget);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (!linetarget)
|
|
|
|
{
|
2009-06-27 19:37:53 +00:00
|
|
|
S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-06-27 19:37:53 +00:00
|
|
|
S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// turn to face target
|
|
|
|
angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y);
|
|
|
|
if (angle - self->angle > ANG180)
|
|
|
|
{
|
|
|
|
if (angle - self->angle < (angle_t)(-ANG90/20))
|
|
|
|
self->angle = angle + ANG90/21;
|
|
|
|
else
|
|
|
|
self->angle -= ANG90/20;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (angle - self->angle > ANG90/20)
|
|
|
|
self->angle = angle - ANG90/21;
|
|
|
|
else
|
|
|
|
self->angle += ANG90/20;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-06-27 19:37:53 +00:00
|
|
|
S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
//A_Chase (self);
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_Punch
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 22:48:37 +00:00
|
|
|
static void MarinePunch(AActor *self, int damagemul)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
angle_t angle;
|
|
|
|
int damage;
|
|
|
|
int pitch;
|
2008-04-10 14:38:43 +00:00
|
|
|
AActor *linetarget;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (self->target == NULL)
|
|
|
|
return;
|
|
|
|
|
2008-08-10 22:48:37 +00:00
|
|
|
damage = ((pr_m_punch()%10+1) << 1) * damagemul;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
A_FaceTarget (self);
|
|
|
|
angle = self->angle + (pr_m_punch.Random2() << 18);
|
2008-04-10 14:38:43 +00:00
|
|
|
pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget);
|
2010-06-13 11:14:01 +00:00
|
|
|
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true, &linetarget);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// turn to face target
|
|
|
|
if (linetarget)
|
|
|
|
{
|
|
|
|
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
|
|
|
|
self->angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-12 14:30:07 +00:00
|
|
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Punch)
|
2008-08-10 22:48:37 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
PARAM_INT(mult);
|
2008-08-10 22:48:37 +00:00
|
|
|
|
2008-08-13 22:54:24 +00:00
|
|
|
MarinePunch(self, mult);
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2008-08-10 22:48:37 +00:00
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// P_GunShot2
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2010-03-24 02:49:37 +00:00
|
|
|
void P_GunShot2 (AActor *mo, bool accurate, int pitch, PClassActor *pufftype)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
angle_t angle;
|
|
|
|
int damage;
|
|
|
|
|
|
|
|
damage = 5*(pr_m_gunshot()%3+1);
|
|
|
|
angle = mo->angle;
|
|
|
|
|
|
|
|
if (!accurate)
|
|
|
|
{
|
|
|
|
angle += pr_m_gunshot.Random2 () << 18;
|
|
|
|
}
|
|
|
|
|
2012-05-13 01:06:28 +00:00
|
|
|
P_LineAttack (mo, angle, MISSILERANGE, pitch, damage, NAME_Hitscan, pufftype);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_FirePistol
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-12 14:30:07 +00:00
|
|
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FirePistol)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
PARAM_BOOL(accurate);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2010-02-12 06:04:57 +00:00
|
|
|
if (self->target == NULL)
|
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
S_Sound (self, CHAN_WEAPON, "weapons/pistol", 1, ATTN_NORM);
|
|
|
|
A_FaceTarget (self);
|
2008-08-05 13:50:57 +00:00
|
|
|
P_GunShot2 (self, accurate, P_AimLineAttack (self, self->angle, MISSILERANGE),
|
2010-03-24 02:49:37 +00:00
|
|
|
PClass::FindActor(NAME_BulletPuff));
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_FireShotgun
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
int pitch;
|
|
|
|
|
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM);
|
|
|
|
A_FaceTarget (self);
|
|
|
|
pitch = P_AimLineAttack (self, self->angle, MISSILERANGE);
|
|
|
|
for (int i = 0; i < 7; ++i)
|
|
|
|
{
|
2010-03-24 02:49:37 +00:00
|
|
|
P_GunShot2 (self, false, pitch, PClass::FindActor(NAME_BulletPuff));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
self->special1 = level.maptime + 27;
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_CheckAttack
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_CheckAttack)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->special1 != 0 || self->target == NULL)
|
|
|
|
{
|
2008-08-05 13:50:57 +00:00
|
|
|
self->SetState (self->FindState("SkipAttack"));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
A_FaceTarget (self);
|
|
|
|
}
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_FireShotgun2
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun2)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
int pitch;
|
|
|
|
|
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM);
|
|
|
|
A_FaceTarget (self);
|
|
|
|
pitch = P_AimLineAttack (self, self->angle, MISSILERANGE);
|
|
|
|
for (int i = 0; i < 20; ++i)
|
|
|
|
{
|
|
|
|
int damage = 5*(pr_m_fireshotgun2()%3+1);
|
|
|
|
angle_t angle = self->angle + (pr_m_fireshotgun2.Random2() << 19);
|
|
|
|
|
|
|
|
P_LineAttack (self, angle, MISSILERANGE,
|
|
|
|
pitch + (pr_m_fireshotgun2.Random2() * 332063), damage,
|
2012-06-17 03:18:26 +00:00
|
|
|
NAME_Hitscan, NAME_BulletPuff);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
self->special1 = level.maptime;
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_FireCGun
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-12 14:30:07 +00:00
|
|
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FireCGun)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
PARAM_BOOL(accurate);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2010-02-12 06:04:57 +00:00
|
|
|
if (self->target == NULL)
|
|
|
|
return 0;
|
2008-08-05 13:50:57 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM);
|
|
|
|
A_FaceTarget (self);
|
2008-08-05 13:50:57 +00:00
|
|
|
P_GunShot2 (self, accurate, P_AimLineAttack (self, self->angle, MISSILERANGE),
|
2010-03-24 02:49:37 +00:00
|
|
|
PClass::FindActor(NAME_BulletPuff));
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_FireMissile
|
|
|
|
//
|
|
|
|
// Giving a marine a rocket launcher is probably a bad idea unless you pump
|
|
|
|
// up his health, because he's just as likely to kill himself as he is to
|
|
|
|
// kill anything else with it.
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_FireMissile)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (self->CheckMeleeRange ())
|
|
|
|
{ // If too close, punch it
|
2008-08-10 22:48:37 +00:00
|
|
|
MarinePunch(self, 1);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
A_FaceTarget (self);
|
2010-04-03 04:07:17 +00:00
|
|
|
P_SpawnMissile (self, self->target, PClass::FindActor("Rocket"));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_FireRailgun
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_FireRailgun)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2008-08-10 22:48:37 +00:00
|
|
|
CALL_ACTION(A_MonsterRail, self);
|
2006-02-24 04:48:15 +00:00
|
|
|
self->special1 = level.maptime + 50;
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_FirePlasma
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_FirePlasma)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
A_FaceTarget (self);
|
2010-04-03 04:07:17 +00:00
|
|
|
P_SpawnMissile (self, self->target, PClass::FindActor("PlasmaBall"));
|
2006-02-24 04:48:15 +00:00
|
|
|
self->special1 = level.maptime + 20;
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_BFGsound
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_BFGsound)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (self->special1 != 0)
|
|
|
|
{
|
|
|
|
self->SetState (self->SeeState);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
A_FaceTarget (self);
|
|
|
|
S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM);
|
|
|
|
// Don't interrupt the firing sequence
|
|
|
|
self->PainChance = 0;
|
|
|
|
}
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_M_FireBFG
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_M_FireBFG)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
A_FaceTarget (self);
|
2010-04-03 04:07:17 +00:00
|
|
|
P_SpawnMissile (self, self->target, PClass::FindActor("BFGBall"));
|
2006-02-24 04:48:15 +00:00
|
|
|
self->special1 = level.maptime + 30;
|
|
|
|
self->PainChance = MARINE_PAIN_CHANCE;
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void AScriptedMarine::SetWeapon (EMarineWeapon type)
|
|
|
|
{
|
2008-08-05 13:50:57 +00:00
|
|
|
if (GetWeaponStates(type, MeleeState, MissileState))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-08-05 13:50:57 +00:00
|
|
|
static const char *classes[] = {
|
|
|
|
"ScriptedMarine",
|
|
|
|
"MarineFist",
|
|
|
|
"MarineBerserk",
|
|
|
|
"MarineChainsaw",
|
|
|
|
"MarinePistol",
|
|
|
|
"MarineShotgun",
|
|
|
|
"MarineSSG",
|
|
|
|
"MarineChaingun",
|
|
|
|
"MarineRocket",
|
|
|
|
"MarinePlasma",
|
|
|
|
"MarineRailgun",
|
|
|
|
"MarineBFG"
|
|
|
|
};
|
|
|
|
|
|
|
|
const PClass *cls = PClass::FindClass(classes[type]);
|
|
|
|
if (cls != NULL)
|
|
|
|
DecalGenerator = GetDefaultByType(cls)->DecalGenerator;
|
|
|
|
else
|
|
|
|
DecalGenerator = NULL;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-14 03:04:41 +00:00
|
|
|
void AScriptedMarine::SetSprite (PClassActor *source)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-03-24 02:49:37 +00:00
|
|
|
if (source == NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // A valid actor class wasn't passed, so use the standard sprite
|
2010-03-24 02:49:37 +00:00
|
|
|
SpriteOverride = sprite = GetClass()->OwnedStates[0].sprite;
|
2009-11-29 01:56:22 +00:00
|
|
|
// Copy the standard scaling
|
|
|
|
scaleX = GetDefault()->scaleX;
|
|
|
|
scaleY = GetDefault()->scaleY;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
2009-11-29 01:56:22 +00:00
|
|
|
{ // Use the same sprite and scaling the passed class spawns with
|
2008-08-10 14:19:47 +00:00
|
|
|
SpriteOverride = sprite = GetDefaultByType (source)->SpawnState->sprite;
|
2006-11-14 16:54:02 +00:00
|
|
|
scaleX = GetDefaultByType(source)->scaleX;
|
|
|
|
scaleY = GetDefaultByType(source)->scaleY;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|