vkdoom_m/src/g_hexen/a_clericstaff.cpp
Christoph Oelckers a2f4cd7cda - fixed: All functions that are callable from weapon states and not members of Actor need to be declared 'action'.
With the stricter type checks of the self pointer that were now implemented these all produced errors.
2016-11-13 14:20:30 +01:00

199 lines
4.6 KiB
C++

/*
#include "actor.h"
#include "gi.h"
#include "m_random.h"
#include "s_sound.h"
#include "d_player.h"
#include "a_action.h"
#include "p_local.h"
#include "a_action.h"
#include "p_pspr.h"
#include "gstrings.h"
#include "a_hexenglobal.h"
#include "vm.h"
*/
static FRandom pr_staffcheck ("CStaffCheck");
static FRandom pr_blink ("CStaffBlink");
// Serpent Staff Missile ----------------------------------------------------
class ACStaffMissile : public AActor
{
DECLARE_CLASS (ACStaffMissile, AActor)
public:
int DoSpecialDamage (AActor *target, int damage, FName damagetype);
};
IMPLEMENT_CLASS(ACStaffMissile, false, false, false, false)
int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetype)
{
// Cleric Serpent Staff does poison damage
if (target->player)
{
P_PoisonPlayer (target->player, this, this->target, 20);
damage >>= 1;
}
return damage;
}
//============================================================================
//
// A_CStaffCheck
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
{
PARAM_ACTION_PROLOGUE(AActor);
APlayerPawn *pmo;
int damage;
int newLife, max;
DAngle angle;
DAngle slope;
int i;
player_t *player;
FTranslatedLineTarget t;
PClassActor *puff;
if (nullptr == (player = self->player))
{
return 0;
}
AWeapon *weapon = self->player->ReadyWeapon;
pmo = player->mo;
damage = 20 + (pr_staffcheck() & 15);
max = pmo->GetMaxHealth();
puff = PClass::FindActor("CStaffPuff");
for (i = 0; i < 3; i++)
{
for (int j = 1; j >= -1; j -= 2)
{
angle = pmo->Angles.Yaw + j*i*(45. / 16);
slope = P_AimLineAttack(pmo, angle, 1.5 * MELEERANGE, &t, 0., ALF_CHECK3D);
if (t.linetarget)
{
P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage, NAME_Melee, puff, false, &t);
if (t.linetarget != nullptr)
{
pmo->Angles.Yaw = t.angleFromSource;
if (((t.linetarget->player && (!t.linetarget->IsTeammate(pmo) || level.teamdamage != 0)) || t.linetarget->flags3&MF3_ISMONSTER)
&& (!(t.linetarget->flags2&(MF2_DORMANT | MF2_INVULNERABLE))))
{
newLife = player->health + (damage >> 3);
newLife = newLife > max ? max : newLife;
if (newLife > player->health)
{
pmo->health = player->health = newLife;
}
if (weapon != nullptr)
{
FState * newstate = weapon->FindState("Drain");
if (newstate != nullptr) P_SetPsprite(player, PSP_WEAPON, newstate);
}
}
if (weapon != nullptr)
{
weapon->DepleteAmmo(weapon->bAltFire, false);
}
}
return 0;
}
}
}
return 0;
}
//============================================================================
//
// A_CStaffAttack
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack)
{
PARAM_ACTION_PROLOGUE(AActor);
AActor *mo;
player_t *player;
if (NULL == (player = self->player))
{
return 0;
}
AWeapon *weapon = self->player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->Angles.Yaw - 3.0);
if (mo)
{
mo->WeaveIndexXY = 32;
}
mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->Angles.Yaw + 3.0);
if (mo)
{
mo->WeaveIndexXY = 0;
}
S_Sound (self, CHAN_WEAPON, "ClericCStaffFire", 1, ATTN_NORM);
return 0;
}
//============================================================================
//
// A_CStaffMissileSlither
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither)
{
PARAM_SELF_PROLOGUE(AActor);
A_Weave(self, 3, 0, 1., 0.);
return 0;
}
//============================================================================
//
// A_CStaffInitBlink
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CStaffInitBlink)
{
PARAM_ACTION_PROLOGUE(AActor);
self->weaponspecial = (pr_blink()>>1)+20;
return 0;
}
//============================================================================
//
// A_CStaffCheckBlink
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheckBlink)
{
PARAM_ACTION_PROLOGUE(AActor);
if (self->player && self->player->ReadyWeapon)
{
if (!--self->weaponspecial)
{
P_SetPsprite(self->player, PSP_WEAPON, self->player->ReadyWeapon->FindState ("Blink"));
self->weaponspecial = (pr_blink()+50)>>2;
}
else
{
DoReadyWeapon(self);
}
}
return 0;
}