void AScriptedMarine::Tick () { Super::Tick (); // Override the standard sprite, if desired if (SpriteOverride != 0 && sprite == GetClass()->ActorInfo->OwnedStates[0].sprite) { sprite = SpriteOverride; } if (special1 != 0) { if (CurrentWeapon == WEAPON_SuperShotgun) { // 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); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( this, CHAN_WEAPON, "weapons/sshoto", 1, ATTN_NORM ); break; case 28: S_Sound (this, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( this, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM ); break; case 41: S_Sound (this, CHAN_WEAPON, "weapons/sshotc", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( 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; } } } }
DEFINE_ACTION_FUNCTION(AActor, A_GetHurt) { // [BB] The server handles this. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { if (( self->ulNetworkFlags & NETFL_CLIENTSIDEONLY ) == false ) return; } self->flags4 |= MF4_INCOMBAT; if ((pr_gethurt() % 5) == 0) { S_Sound (self, CHAN_VOICE, self->PainSound, 1, ATTN_NORM); // [BB] If we're the server, tell clients to play the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_VOICE, S_GetName( self->PainSound ), 1, ATTN_NORM ); self->health--; } if (self->health <= 0) { self->Die (self->target, self->target); } }
DEFINE_ACTION_FUNCTION(AActor, A_TemplarAttack) { int damage; angle_t angle; int pitch; int pitchdiff; if (self->target == NULL) return; S_Sound (self, CHAN_WEAPON, "templar/shoot", 1, ATTN_NORM); // [CW] Tell clients to play the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "templar/shoot", 1, ATTN_NORM ); A_FaceTarget (self); pitch = P_AimLineAttack (self, self->angle, MISSILERANGE); for (int i = 0; i < 10; ++i) { damage = (pr_templar() & 4) * 2; angle = self->angle + (pr_templar.Random2() << 19); pitchdiff = pr_templar.Random2() * 332063; P_LineAttack (self, angle, MISSILERANGE+64*FRACUNIT, pitch+pitchdiff, damage, NAME_None, NAME_MaulerPuff); } }
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_M_BFGsound) { // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; if (self->special1 != 0) { self->SetState (self->SeeState); } else { A_FaceTarget (self); S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM ); // Don't interrupt the firing sequence self->PainChance = 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_M_FireShotgun2) { int pitch; // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( 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, NAME_None, PClass::FindClass(NAME_BulletPuff)); } self->special1 = level.maptime; }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FireCGun) { // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; ACTION_PARAM_START(1); ACTION_PARAM_BOOL(accurate, 0); S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM ); A_FaceTarget (self); P_GunShot2 (self, accurate, P_AimLineAttack (self, self->angle, MISSILERANGE), PClass::FindClass(NAME_BulletPuff)); }
DEFINE_ACTION_FUNCTION(AActor, A_BishopDoBlur) { // [BB] This is server-side. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } self->special1 = (pr_doblur() & 3) + 3; // Random number of blurs if (pr_doblur() < 120) { P_ThrustMobj (self, self->angle + ANG90, 11*FRACUNIT); } else if (pr_doblur() > 125) { P_ThrustMobj (self, self->angle - ANG90, 11*FRACUNIT); } else { // Thrust forward P_ThrustMobj (self, self->angle, 11*FRACUNIT); } S_Sound (self, CHAN_BODY, "BishopBlur", 1, ATTN_NORM); // [BB] If we're the server, update the thing's momentum and play the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_MoveThingExact( self, CM_MOMX|CM_MOMY ); SERVERCOMMANDS_SoundActor( self, CHAN_BODY, "BishopBlur", 1, ATTN_NORM ); } }
DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun) { int pitch; // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( 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) { P_GunShot2 (self, false, pitch, PClass::FindClass(NAME_BulletPuff)); } self->special1 = level.maptime + 27; }
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 ); }
DEFINE_ACTION_FUNCTION(AActor, A_SerpentHumpDecide) { // [BB] This is server-side. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->MissileState != NULL) { if (pr_serpenthump() > 30) { return; } else if (pr_serpenthump() < 40) { // Missile attack // [BB] If we're the server, set the thing's state. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SetThingState( self, STATE_MELEE ); self->SetState (self->MeleeState); return; } } else if (pr_serpenthump() > 3) { return; } if (!self->CheckMeleeRange ()) { // The hump shouldn't occur when within melee range if (self->MissileState != NULL && pr_serpenthump() < 128) { // [BB] If we're the server, set the thing's state. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SetThingState( self, STATE_MELEE ); self->SetState (self->MeleeState); } else { // [BB] If we're the server, set the thing's state and play the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_SetThingFrame( self, self->FindState ("Hump") ); SERVERCOMMANDS_SoundActor( self, CHAN_BODY, "SerpentActive", 1, ATTN_NORM ); } self->SetState (self->FindState ("Hump")); S_Sound (self, CHAN_BODY, "SerpentActive", 1, ATTN_NORM); } } }
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_MarineNoise) { // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (static_cast<AScriptedMarine *>(self)->CurrentWeapon == AScriptedMarine::WEAPON_Chainsaw) { S_Sound (self, CHAN_WEAPON, "weapons/sawidle", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/sawidle", 1, ATTN_NORM ); } }
DEFINE_ACTION_FUNCTION(AActor, A_ShootGun) { int pitch; if (self->target == NULL) return; // [BC] Play this sound to clients. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "monsters/rifle", 1, ATTN_NORM ); S_Sound (self, CHAN_WEAPON, "monsters/rifle", 1, ATTN_NORM); A_FaceTarget (self); pitch = P_AimLineAttack (self, self->angle, MISSILERANGE); P_LineAttack (self, self->angle + (pr_shootgun.Random2() << 19), MISSILERANGE, pitch, 3*(pr_shootgun() % 5 + 1), NAME_None, NAME_StrifePuff); }
void A_SkullAttack(AActor *self, fixed_t speed) { AActor *dest; angle_t an; int dist; // [BC] This is handled server-side. if ( NETWORK_InClientMode() ) { return; } if (!self->target) return; dest = self->target; self->flags |= MF_SKULLFLY; S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM); // [BC] If we're the server, tell clients play this sound. // [BB] And tell them of MF_SKULLFLY. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_SetThingFlags( self, FLAGSET_FLAGS ); SERVERCOMMANDS_SoundActor( self, CHAN_VOICE, S_GetName( self->AttackSound ), 1, ATTN_NORM ); } A_FaceTarget (self); an = self->angle >> ANGLETOFINESHIFT; self->velx = FixedMul (speed, finecosine[an]); self->vely = FixedMul (speed, finesine[an]); dist = P_AproxDistance (dest->x - self->x, dest->y - self->y); dist = dist / speed; if (dist < 1) dist = 1; self->velz = (dest->z + (dest->height>>1) - self->z) / dist; // [BC] Update the lost soul's momentum. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_MoveThingExact( self, CM_X|CM_Y|CM_Z|CM_MOMX|CM_MOMY|CM_MOMZ ); }
DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack) { angle_t angle; int damage; int slope; player_t *player; AActor *puff; AActor *linetarget; if (NULL == (player = self->player)) { return; } damage = 3+(pr_snoutattack()&3); angle = player->mo->angle; slope = P_AimLineAttack(player->mo, angle, MELEERANGE, &linetarget); puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "SnoutPuff", true); S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM); // [Dusk] clients aren't properly aware of linetarget, thus they stop here. if (NETWORK_InClientMode()) return; if(linetarget) { AdjustPlayerAngle(player->mo, linetarget); // [Dusk] update angle if (NETWORK_GetState() == NETSTATE_SERVER) SERVERCOMMANDS_MoveThing(player->mo, CM_ANGLE); if(puff != NULL) { // Bit something S_Sound(player->mo, CHAN_VOICE, "PigAttack", 1, ATTN_NORM); // [Dusk] tell clients of the attack sound if (NETWORK_GetState() == NETSTATE_SERVER) SERVERCOMMANDS_SoundActor (player->mo, CHAN_VOICE, "PigAttack", 1, ATTN_NORM); } } }
static void MarinePunch(AActor *self, int damagemul) { angle_t angle; int damage; int pitch; AActor *linetarget; // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; damage = ((pr_m_punch()%10+1) << 1) * damagemul; A_FaceTarget (self); angle = self->angle + (pr_m_punch.Random2() << 18); pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget); P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true); // turn to face target if (linetarget) { S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "*fist", 1, ATTN_NORM ); self->angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y); } }
DEFINE_ACTION_FUNCTION(AActor, A_FiredAttack) { // [BC] Let the server do this. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; AActor *mo = P_SpawnMissile (self, self->target, PClass::FindClass ("FireDemonMissile")); if (mo) { S_Sound (self, CHAN_BODY, "FireDemonAttack", 1, ATTN_NORM); // [BC] If we're the server, spawn this and make the sound for clients. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_SpawnMissile( mo ); SERVERCOMMANDS_SoundActor( self, CHAN_BODY, "FireDemonAttack", 1, ATTN_NORM ); } } }
DEFINE_ACTION_FUNCTION(AActor, A_M_Saw) { // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; A_FaceTarget (self); if (self->CheckMeleeRange ()) { angle_t angle; int damage; AActor *linetarget; damage = 2 * (pr_m_saw()%10+1); angle = self->angle + (pr_m_saw.Random2() << 18); P_LineAttack (self, angle, MELEERANGE+1, P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage, NAME_Melee, NAME_BulletPuff); if (!linetarget) { S_Sound (self, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM ); return; } S_Sound (self, CHAN_WEAPON, "weapons/sawhit", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/sawhit", 1, ATTN_NORM ); // 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 { S_Sound (self, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM ); } //A_Chase (self); }
bool AArtiTeleport::Use (bool pickup) { fixed_t destX; fixed_t destY; angle_t destAngle; // [BC] Let the server decide where we go. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return ( true ); } // [BB] If this is a team game and there are valid team starts for the team // the owner is on, teleport to one of the team starts. const ULONG ownerTeam = Owner->player ? Owner->player->ulTeam : teams.Size( ); if ( ( GAMEMODE_GetFlags( GAMEMODE_GetCurrentMode( )) & GMF_PLAYERSONTEAMS ) && TEAM_CheckIfValid ( ownerTeam ) && ( teams[ownerTeam].TeamStarts.Size( ) > 0 ) ) { unsigned int selections = teams[ownerTeam].TeamStarts.Size (); unsigned int i = pr_tele() % selections; destX = teams[ownerTeam].TeamStarts[i].x; destY = teams[ownerTeam].TeamStarts[i].y; destAngle = ANG45 * (teams[ownerTeam].TeamStarts[i].angle/45); } else if (deathmatch) { unsigned int selections = deathmatchstarts.Size (); unsigned int i = pr_tele() % selections; destX = deathmatchstarts[i].x; destY = deathmatchstarts[i].y; destAngle = ANG45 * (deathmatchstarts[i].angle/45); } else { FMapThing *pSpot = NULL; // [BB] If there is a designated start for this player use it. if ( playerstarts[Owner->player - players].type != 0 ) pSpot = &playerstarts[Owner->player - players]; // [BB] Otherwise we just have to select a start at random from all available player starts. else pSpot = SelectRandomCooperativeSpot( Owner->player - players ); if ( pSpot != NULL ) { destX = pSpot->x; destY = pSpot->y; destAngle = ANG45 * (pSpot->angle/45); } else I_Error( "ArtiTeleport: No player start found!" ); } P_Teleport (Owner, destX, destY, ONFLOORZ, destAngle, true, true, false); bool canlaugh = true; if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYCHAOSDEVICE)) { // Teleporting away will undo any morph effects (pig) if (!P_UndoPlayerMorph (Owner->player, Owner->player, MORPH_UNDOBYCHAOSDEVICE) && (Owner->player->MorphStyle & MORPH_FAILNOLAUGH)) { canlaugh = false; } } if (canlaugh) { // Full volume laugh S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_NONE); // [BC] Play the laugh for clients. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_NONE ); } return true; }