DEFINE_ACTION_FUNCTION(AActor, A_KnightAttack) { PARAM_ACTION_PROLOGUE; if (!self->target) { return 0; } if (self->CheckMeleeRange ()) { int damage = pr_knightatk.HitDice (3); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); S_Sound (self, CHAN_BODY, "hknight/melee", 1, ATTN_NORM); return 0; } // Throw axe S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM); if (self->flags & MF_SHADOW || pr_knightatk () < 40) { // Red axe P_SpawnMissileZ (self, self->Z() + 36, self->target, PClass::FindActor("RedAxe")); return 0; } // Green axe P_SpawnMissileZ (self, self->Z() + 36, self->target, PClass::FindActor("KnightAxe")); return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_SerpentMeleeAttack) { // [BB] This is server-side. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (!self->target) { return; } if (self->CheckMeleeRange ()) { int damage = pr_serpentmeattack.HitDice (5); P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (damage, self->target, self); S_Sound (self, CHAN_BODY, "SerpentMeleeHit", 1, ATTN_NORM); // [BB] If we're the server, tell the clients to play the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_BODY, "SerpentMeleeHit", 1, ATTN_NORM ); } if (pr_serpentmeattack() < 96) { CALL_ACTION(A_SerpentCheckForAttack, self); } }
DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack) { // [BB] This is server-side. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (!self->target) { return; } S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM); // [BB] If we're the server, tell the clients to play the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_BODY, S_GetName(self->AttackSound), 1, ATTN_NORM ); if (self->CheckMeleeRange()) { int damage = pr_atk.HitDice (4); P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (damage, self->target, self); return; } self->special1 = (pr_atk() & 3) + 5; }
DEFINE_ACTION_FUNCTION(AActor, A_BruisAttack) { AActor *pMissile; if (!self->target) return; if (self->CheckMeleeRange ()) { int damage = (pr_bruisattack()%8+1)*10; S_Sound (self, CHAN_WEAPON, "baron/melee", 1, ATTN_NORM); // [BC] If we're the server, tell clients play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "baron/melee", 1, ATTN_NORM ); P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (damage, self->target, self); return; } // launch a missile pMissile = P_SpawnMissile (self, self->target, PClass::FindClass("BaronBall")); // [BC] If we're the server, tell clients to spawn the missile. if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( pMissile )) SERVERCOMMANDS_SpawnMissile( pMissile ); }
void A_Srcr2Attack (AActor *actor) { int chance; if (!actor->target) { return; } S_SoundID (actor, CHAN_BODY, actor->AttackSound, 1, ATTN_NONE); if (actor->CheckMeleeRange()) { int damage = pr_s2a.HitDice (20); P_DamageMobj (actor->target, actor, actor, damage, NAME_Melee); P_TraceBleed (damage, actor->target, actor); return; } chance = actor->health < actor->GetDefault()->health/2 ? 96 : 48; if (pr_s2a() < chance) { // Wizard spawners P_SpawnMissileAngle (actor, RUNTIME_CLASS(ASorcerer2FX2), actor->angle-ANG45, FRACUNIT/2); P_SpawnMissileAngle (actor, RUNTIME_CLASS(ASorcerer2FX2), actor->angle+ANG45, FRACUNIT/2); } else { // Blue bolt P_SpawnMissile (actor, actor->target, RUNTIME_CLASS(ASorcerer2FX1)); } }
DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Attack) { int chance; if (!self->target) { return; } S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NONE); if (self->CheckMeleeRange()) { int damage = pr_s2a.HitDice (20); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); return; } chance = self->health < self->SpawnHealth()/2 ? 96 : 48; if (pr_s2a() < chance) { // Wizard spawners const PClass *fx = PClass::FindClass("Sorcerer2FX2"); if (fx) { P_SpawnMissileAngle (self, fx, self->angle-ANG45, FRACUNIT/2); P_SpawnMissileAngle (self, fx, self->angle+ANG45, FRACUNIT/2); } } else { // Blue bolt P_SpawnMissile (self, self->target, PClass::FindClass("Sorcerer2FX1")); } }
DEFINE_ACTION_FUNCTION(AActor, A_ChicAttack) { if (!self->target) { return; } if (self->CheckMeleeRange()) { int damage = 1 + (pr_chicattack() & 1); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); } }
void A_ImpMeAttack (AActor *self) { if (!self->target) { return; } S_SoundID (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); if (self->CheckMeleeRange ()) { int damage = 5+(pr_impmeatk()&7); P_DamageMobj (self->target, self, self, damage, MOD_HIT); P_TraceBleed (damage, self->target, self); } }
DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack) { PARAM_ACTION_PROLOGUE; AActor *mo; DAngle angle; if (!self->target) { return 0; } S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM); if (self->CheckMeleeRange ()) { int damage = pr_scrc1atk.HitDice (8); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); return 0; } PClassActor *fx = PClass::FindActor("SorcererFX1"); if (self->health > (self->SpawnHealth()/3)*2) { // Spit one fireball P_SpawnMissileZ (self, self->Z() + 48, self->target, fx ); } else { // Spit three fireballs mo = P_SpawnMissileZ (self, self->Z() + 48, self->target, fx); if (mo != NULL) { angle = mo->Angles.Yaw; P_SpawnMissileAngleZ(self, self->Z() + 48, fx, angle - 3, mo->Vel.Z); P_SpawnMissileAngleZ(self, self->Z() + 48, fx, angle + 3, mo->Vel.Z); } if (self->health < self->SpawnHealth()/3) { // Maybe attack again if (self->special1) { // Just attacked, so don't attack again self->special1 = 0; } else { // Set state to attack again self->special1 = 1; self->SetState (self->FindState("Missile2")); } } } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk3) { PARAM_ACTION_PROLOGUE; AActor *mo; player_t *player; bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER); if (!self->target) { return 0; } S_Sound (self, CHAN_VOICE, "minotaur/attack3", 1, ATTN_NORM); if (self->CheckMeleeRange()) { int damage; damage = pr_minotauratk3.HitDice (friendly ? 3 : 5); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); if ((player = self->target->player) != NULL && player->mo == self->target) { // Squish the player player->deltaviewheight = -16; } } else { if (self->Floorclip > 0 && (i_compatflags & COMPATF_MINOTAUR)) { // only play the sound. S_Sound (self, CHAN_WEAPON, "minotaur/fx2hit", 1, ATTN_NORM); } else { mo = P_SpawnMissile (self, self->target, PClass::FindActor("MinotaurFX2")); if (mo != NULL) { S_Sound (mo, CHAN_WEAPON, "minotaur/attack1", 1, ATTN_NORM); } } } if (pr_minotauratk3() < 192 && self->special2 == 0) { self->SetState (self->FindState ("HammerLoop")); self->special2 = 1; } return 0; }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack) { ACTION_PARAM_START(7); ACTION_PARAM_SOUND(snd,0); ACTION_PARAM_INT(dmg,1); ACTION_PARAM_INT(blastdmg,2); ACTION_PARAM_INT(blastrad,3); ACTION_PARAM_FIXED(thrust,4); ACTION_PARAM_NAME(dmgtype,5); ACTION_PARAM_INT(flags,6); AActor *fire, *target; angle_t an; if (NULL == (target = self->target)) return; A_FaceTarget (self); if (!P_CheckSight (self, target, 0) ) return; S_Sound (self, CHAN_WEAPON, snd, 1, ATTN_NORM); int newdam; if (flags & VAF_DMGTYPEAPPLYTODIRECT) newdam = P_DamageMobj (target, self, self, dmg, dmgtype); else newdam = P_DamageMobj (target, self, self, dmg, NAME_None); P_TraceBleed (newdam > 0 ? newdam : dmg, target); an = self->angle >> ANGLETOFINESHIFT; fire = self->tracer; if (fire != NULL) { // move the fire between the vile and the player fire->SetOrigin (target->x - FixedMul (24*FRACUNIT, finecosine[an]), target->y - FixedMul (24*FRACUNIT, finesine[an]), target->z); P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0); } if (!(target->flags7 & MF7_DONTTHRUST)) target->velz = Scale(thrust, 1000, target->Mass); }
DEFINE_ACTION_FUNCTION(AActor, A_WizAtk3) { AActor *mo; CALL_ACTION(A_GhostOff, self); // [BB] This is server-side, the client only needs to run A_GhostOff. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (!self->target) { return; } S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); // [BB] If we're the server, tell the clients to play the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, S_GetName( self->AttackSound ), 1, ATTN_NORM ); if (self->CheckMeleeRange()) { int damage = pr_wizatk3.HitDice (4); P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (damage, self->target, self); return; } const PClass *fx = PClass::FindClass("WizardFX1"); mo = P_SpawnMissile (self, self->target, fx); if (mo != NULL) { AActor *missile1 = P_SpawnMissileAngle(self, fx, mo->angle-(ANG45/8), mo->velz); AActor *missile2 = P_SpawnMissileAngle(self, fx, mo->angle+(ANG45/8), mo->velz); // [BB] If we're the server, tell the clients to spawn the missiles. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_SpawnMissile( mo ); if ( missile1 ) SERVERCOMMANDS_SpawnMissile( missile1 ); if ( missile2 ) SERVERCOMMANDS_SpawnMissile( missile2 ); } } }
DEFINE_ACTION_FUNCTION(AActor, A_SkelFist) { if (!self->target) return; A_FaceTarget (self); if (self->CheckMeleeRange ()) { int damage = ((pr_skelfist()%10)+1)*6; S_Sound (self, CHAN_WEAPON, "skeleton/melee", 1, ATTN_NORM); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); } }
DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack) { AActor *mo; fixed_t velz; angle_t angle; if (!self->target) { return; } S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM); if (self->CheckMeleeRange ()) { int damage = pr_scrc1atk.HitDice (8); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); return; } const PClass *fx = PClass::FindClass("SorcererFX1"); if (self->health > (self->SpawnHealth()/3)*2) { // Spit one fireball P_SpawnMissileZ (self, self->Z() + 48*FRACUNIT, self->target, fx ); } else { // Spit three fireballs mo = P_SpawnMissileZ (self, self->Z() + 48*FRACUNIT, self->target, fx); if (mo != NULL) { velz = mo->velz; angle = mo->angle; P_SpawnMissileAngleZ (self, self->Z() + 48*FRACUNIT, fx, angle-ANGLE_1*3, velz); P_SpawnMissileAngleZ (self, self->Z() + 48*FRACUNIT, fx, angle+ANGLE_1*3, velz); } if (self->health < self->SpawnHealth()/3) { // Maybe attack again if (self->special1) { // Just attacked, so don't attack again self->special1 = 0; } else { // Set state to attack again self->special1 = 1; self->SetState (self->FindState("Missile2")); } } } }
DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack) { if (!self->target) { return; } S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM); if (self->CheckMeleeRange()) { int damage = pr_atk.HitDice (4); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); return; } self->special1 = (pr_atk() & 3) + 5; }
void A_ImpMsAttack2 (AActor *self) { if (!self->target) { return; } S_SoundID (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); if (self->CheckMeleeRange ()) { int damage = 5+(pr_impmsatk2()&7); P_DamageMobj (self->target, self, self, damage, MOD_HIT); P_TraceBleed (damage, self->target, self); return; } P_SpawnMissile (self, self->target, RUNTIME_CLASS(AHereticImpBall)); }
DEFINE_ACTION_FUNCTION(AActor, A_SargAttack) { PARAM_ACTION_PROLOGUE; if (!self->target) return 0; A_FaceTarget (self); if (self->CheckMeleeRange ()) { int damage = ((pr_sargattack()%10)+1)*4; int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); } return 0; }
void P_MinotaurSlam (AActor *source, AActor *target) { DAngle angle; double thrust; int damage; angle = source->AngleTo(target); thrust = 16 + pr_minotaurslam() / 64.; target->VelFromAngle(angle, thrust); damage = pr_minotaurslam.HitDice (static_cast<AMinotaur *>(source) ? 4 : 6); int newdam = P_DamageMobj (target, NULL, NULL, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, target, angle, 0.); if (target->player) { target->reactiontime = 14+(pr_minotaurslam()&7); } }
void A_Srcr1Attack (AActor *actor) { AActor *mo; fixed_t momz; angle_t angle; if (!actor->target) { return; } S_SoundID (actor, CHAN_BODY, actor->AttackSound, 1, ATTN_NORM); if (actor->CheckMeleeRange ()) { int damage = pr_scrc1atk.HitDice (8); P_DamageMobj (actor->target, actor, actor, damage, NAME_Melee); P_TraceBleed (damage, actor->target, actor); return; } if (actor->health > (actor->GetDefault()->health/3)*2) { // Spit one fireball P_SpawnMissileZ (actor, actor->z + 48*FRACUNIT, actor->target, RUNTIME_CLASS(ASorcererFX1)); } else { // Spit three fireballs mo = P_SpawnMissileZ (actor, actor->z + 48*FRACUNIT, actor->target, RUNTIME_CLASS(ASorcererFX1)); if (mo != NULL) { momz = mo->momz; angle = mo->angle; P_SpawnMissileAngleZ (actor, actor->z + 48*FRACUNIT, RUNTIME_CLASS(ASorcererFX1), angle-ANGLE_1*3, momz); P_SpawnMissileAngleZ (actor, actor->z + 48*FRACUNIT, RUNTIME_CLASS(ASorcererFX1), angle+ANGLE_1*3, momz); } if (actor->health < actor->GetDefault()->health/3) { // Maybe attack again if (actor->special1) { // Just attacked, so don't attack again actor->special1 = 0; } else { // Set state to attack again actor->special1 = 1; actor->SetState (&ASorcerer1::States[S_SRCR1_ATK+3]); } } } }
DEFINE_ACTION_FUNCTION(AActor, A_SerpentMeleeAttack) { if (!self->target) { return; } if (self->CheckMeleeRange ()) { int damage = pr_serpentmeattack.HitDice (5); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); S_Sound (self, CHAN_BODY, "SerpentMeleeHit", 1, ATTN_NORM); } if (pr_serpentmeattack() < 96) { CALL_ACTION(A_SerpentCheckForAttack, self); } }
DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerMelee) { int damage; if (self->target == NULL) return; A_FaceTarget (self); if (!self->CheckMeleeRange ()) return; S_Sound (self, CHAN_WEAPON, "programmer/clank", 1, ATTN_NORM); damage = ((pr_prog() % 10) + 1) * 6; int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); }
// // A_TroopAttack // DEFINE_ACTION_FUNCTION(AActor, A_TroopAttack) { if (!self->target) return; A_FaceTarget (self); if (self->CheckMeleeRange ()) { int damage = (pr_troopattack()%8+1)*3; S_Sound (self, CHAN_WEAPON, "imp/melee", 1, ATTN_NORM); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); return; } // launch a missile P_SpawnMissile (self, self->target, PClass::FindClass("DoomImpBall")); }
DEFINE_ACTION_FUNCTION(AActor, A_StalkerAttack) { if (self->flags & MF_NOGRAVITY) { self->SetState (self->FindState("Drop")); } else if (self->target != NULL) { A_FaceTarget (self); if (self->CheckMeleeRange ()) { int damage = (pr_stalker() & 7) * 2 + 2; int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); } } }
DEFINE_ACTION_FUNCTION(AActor, A_HeadAttack) { if (!self->target) return; A_FaceTarget (self); if (self->CheckMeleeRange ()) { int damage = (pr_headattack()%6+1)*10; S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); return; } // launch a missile P_SpawnMissile (self, self->target, PClass::FindClass("CacodemonBall")); }
DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2) { PARAM_ACTION_PROLOGUE; AActor *mo; DAngle angle; double vz; double z; bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER); if (self->target == NULL) { return 0; } S_Sound (self, CHAN_WEAPON, "minotaur/attack2", 1, ATTN_NORM); if (self->CheckMeleeRange()) { int damage; damage = pr_atk.HitDice (friendly ? 3 : 5); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); return 0; } z = self->Z() + 40; PClassActor *fx = PClass::FindActor("MinotaurFX1"); if (fx) { mo = P_SpawnMissileZ (self, z, self->target, fx); if (mo != NULL) { // S_Sound (mo, CHAN_WEAPON, "minotaur/attack2", 1, ATTN_NORM); vz = mo->Vel.Z; angle = mo->Angles.Yaw; P_SpawnMissileAngleZ (self, z, fx, angle-(45./8), vz); P_SpawnMissileAngleZ (self, z, fx, angle+(45./8), vz); P_SpawnMissileAngleZ (self, z, fx, angle-(45./16), vz); P_SpawnMissileAngleZ (self, z, fx, angle+(45./16), vz); } } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk1) { player_t *player; if (!self->target) { return; } S_Sound (self, CHAN_WEAPON, "minotaur/melee", 1, ATTN_NORM); if (self->CheckMeleeRange()) { int damage = pr_minotauratk1.HitDice (4); int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); if ((player = self->target->player) != NULL && player->mo == self->target) { // Squish the player player->deltaviewheight = -16*FRACUNIT; } } }
void A_KnightAttack (AActor *actor) { if (!actor->target) { return; } if (actor->CheckMeleeRange ()) { int damage = pr_knightatk.HitDice (3); P_DamageMobj (actor->target, actor, actor, damage, MOD_HIT); P_TraceBleed (damage, actor->target, actor); S_Sound (actor, CHAN_BODY, "hknight/melee", 1, ATTN_NORM); return; } // Throw axe S_SoundID (actor, CHAN_BODY, actor->AttackSound, 1, ATTN_NORM); if (actor->flags & MF_SHADOW || pr_knightatk () < 40) { // Red axe P_SpawnMissileZ (actor, actor->z + 36*FRACUNIT, actor->target, RUNTIME_CLASS(ARedAxe)); return; } // Green axe P_SpawnMissileZ (actor, actor->z + 36*FRACUNIT, actor->target, RUNTIME_CLASS(AKnightAxe)); }
void A_WizAtk3 (AActor *actor) { AActor *mo; A_GhostOff (actor); if (!actor->target) { return; } S_SoundID (actor, CHAN_WEAPON, actor->AttackSound, 1, ATTN_NORM); if (actor->CheckMeleeRange()) { int damage = pr_wizatk3.HitDice (4); P_DamageMobj (actor->target, actor, actor, damage, NAME_Melee); P_TraceBleed (damage, actor->target, actor); return; } mo = P_SpawnMissile (actor, actor->target, RUNTIME_CLASS(AWizardFX1)); if (mo != NULL) { P_SpawnMissileAngle(actor, RUNTIME_CLASS(AWizardFX1), mo->angle-(ANG45/8), mo->momz); P_SpawnMissileAngle(actor, RUNTIME_CLASS(AWizardFX1), mo->angle+(ANG45/8), mo->momz); } }
DEFINE_ACTION_FUNCTION(AActor, A_LichAttack) { int i; AActor *fire; AActor *baseFire; AActor *mo; AActor *target; int randAttack; static const int atkResolve1[] = { 50, 150 }; static const int atkResolve2[] = { 150, 200 }; int dist; // Ice ball (close 20% : far 60%) // Fire column (close 40% : far 20%) // Whirlwind (close 40% : far 20%) // Distance threshold = 8 cells target = self->target; if (target == NULL) { return; } A_FaceTarget (self); if (self->CheckMeleeRange ()) { int damage = pr_atk.HitDice (6); P_DamageMobj (target, self, self, damage, NAME_Melee); P_TraceBleed (damage, target, self); return; } dist = P_AproxDistance (self->x-target->x, self->y-target->y) > 8*64*FRACUNIT; randAttack = pr_atk (); if (randAttack < atkResolve1[dist]) { // Ice ball P_SpawnMissile (self, target, PClass::FindClass("HeadFX1")); S_Sound (self, CHAN_BODY, "ironlich/attack2", 1, ATTN_NORM); } else if (randAttack < atkResolve2[dist]) { // Fire column baseFire = P_SpawnMissile (self, target, PClass::FindClass("HeadFX3")); if (baseFire != NULL) { baseFire->SetState (baseFire->FindState("NoGrow")); for (i = 0; i < 5; i++) { fire = Spawn("HeadFX3", baseFire->x, baseFire->y, baseFire->z, ALLOW_REPLACE); if (i == 0) { S_Sound (self, CHAN_BODY, "ironlich/attack1", 1, ATTN_NORM); } fire->target = baseFire->target; fire->angle = baseFire->angle; fire->velx = baseFire->velx; fire->vely = baseFire->vely; fire->velz = baseFire->velz; fire->Damage = 0; fire->health = (i+1) * 2; P_CheckMissileSpawn (fire); } } } else { // Whirlwind mo = P_SpawnMissile (self, target, RUNTIME_CLASS(AWhirlwind)); if (mo != NULL) { mo->z -= 32*FRACUNIT; mo->tracer = target; mo->special1 = 60; mo->special2 = 50; // Timer for active sound mo->health = 20*TICRATE; // Duration S_Sound (self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM); } } }