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(AActor, A_SpectralLightning) { PARAM_ACTION_PROLOGUE; AActor *flash; if (self->threshold != 0) --self->threshold; self->Vel.X += pr_zap5.Random2(3); self->Vel.Y += pr_zap5.Random2(3); double xo = pr_zap5.Random2(3) * 50.; double yo = pr_zap5.Random2(3) * 50.; flash = Spawn (self->threshold > 25 ? PClass::FindActor(NAME_SpectralLightningV2) : PClass::FindActor(NAME_SpectralLightningV1), self->Vec2OffsetZ(xo, yo, ONCEILINGZ), ALLOW_REPLACE); flash->target = self->target; flash->Vel.Z = -18; flash->FriendPlayer = self->FriendPlayer; flash = Spawn(NAME_SpectralLightningV2, self->PosAtZ(ONCEILINGZ), ALLOW_REPLACE); flash->target = self->target; flash->Vel.Z = -18; flash->FriendPlayer = self->FriendPlayer; return 0; }
int AWhirlwind::DoSpecialDamage (AActor *target, int damage) { int randVal; target->angle += pr_foo.Random2() << 20; target->velx += pr_foo.Random2() << 10; target->vely += pr_foo.Random2() << 10; if ((level.time & 16) && !(target->flags2 & MF2_BOSS)) { randVal = pr_foo(); if (randVal > 160) { randVal = 160; } target->velz += randVal << 11; if (target->velz > 12*FRACUNIT) { target->velz = 12*FRACUNIT; } } if (!(level.time & 7)) { P_DamageMobj (target, NULL, this->target, 3, NAME_Melee); } return -1; }
DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode) { AActor *mo; int i; for (i = (pr_foo()&3)+3; i; i--) { mo = Spawn ("CorpseBit", self->x, self->y, self->z, ALLOW_REPLACE); if (mo) { mo->SetState (mo->SpawnState + (pr_foo()%3)); mo->velz = ((pr_foo()&7)+5)*(3*FRACUNIT/4); mo->velx = pr_foo.Random2()<<(FRACBITS-6); mo->vely = pr_foo.Random2()<<(FRACBITS-6); } } // Spawn a skull mo = Spawn ("CorpseBit", self->x, self->y, self->z, ALLOW_REPLACE); if (mo) { mo->SetState (mo->SpawnState + 3); mo->velz = ((pr_foo()&7)+5)*(3*FRACUNIT/4); mo->velx = pr_foo.Random2()<<(FRACBITS-6); mo->vely = pr_foo.Random2()<<(FRACBITS-6); } S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_IDLE); self->Destroy (); }
DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightning) { AActor *flash; fixed_t x, y; if (self->threshold != 0) --self->threshold; self->velx += pr_zap5.Random2(3) << FRACBITS; self->vely += pr_zap5.Random2(3) << FRACBITS; x = self->x + pr_zap5.Random2(3) * FRACUNIT * 50; y = self->y + pr_zap5.Random2(3) * FRACUNIT * 50; flash = Spawn (self->threshold > 25 ? PClass::FindClass(NAME_SpectralLightningV2) : PClass::FindClass(NAME_SpectralLightningV1), x, y, ONCEILINGZ, ALLOW_REPLACE); flash->target = self->target; flash->velz = -18*FRACUNIT; flash->FriendPlayer = self->FriendPlayer; flash = Spawn(NAME_SpectralLightningV2, self->x, self->y, ONCEILINGZ, ALLOW_REPLACE); flash->target = self->target; flash->velz = -18*FRACUNIT; flash->FriendPlayer = self->FriendPlayer; }
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_FireMauler1) { PARAM_ACTION_PROLOGUE; if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } // Strife apparently didn't show the player shooting. Let's fix that. self->player->mo->PlayAttacking2 (); } S_Sound (self, CHAN_WEAPON, "weapons/mauler1", 1, ATTN_NORM); int bpitch = P_BulletSlope (self); for (int i = 0; i < 20; ++i) { int damage = 5 * (pr_mauler1() % 3 + 1); angle_t angle = self->angle + (pr_mauler1.Random2() << 19); int pitch = bpitch + (pr_mauler1.Random2() * 332063); // Strife used a range of 2112 units for the mauler to signal that // it should use a different puff. ZDoom's default range is longer // than this, so let's not handicap it by being too faithful to the // original. P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, NAME_MaulerPuff); } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_DripBlood) { AActor *mo; fixed_t xo = (pr_dripblood.Random2() << 11); fixed_t yo = (pr_dripblood.Random2() << 11); mo = Spawn ("Blood", self->Vec3Offset(xo, yo, 0), ALLOW_REPLACE); mo->velx = pr_dripblood.Random2 () << 10; mo->vely = pr_dripblood.Random2 () << 10; mo->gravity = FRACUNIT/8; }
DEFINE_ACTION_FUNCTION(AActor, A_Burnination) { PARAM_ACTION_PROLOGUE; self->Vel.Z -= 8; self->Vel.X += (pr_phburn.Random2 (3)); self->Vel.Y += (pr_phburn.Random2 (3)); S_Sound (self, CHAN_VOICE, "world/largefire", 1, ATTN_NORM); // Only the main fire spawns more. if (!(self->flags & MF_DROPPED)) { // Original x and y offsets seemed to be like this: // x + (((pr_phburn() + 12) & 31) << F.RACBITS); // // But that creates a lop-sided burn because it won't use negative offsets. int xofs, xrand = pr_phburn(); int yofs, yrand = pr_phburn(); // Adding 12 is pointless if you're going to mask it afterward. xofs = xrand & 31; if (xrand & 128) { xofs = -xofs; } yofs = yrand & 31; if (yrand & 128) { yofs = -yofs; } DVector2 pos = self->Vec2Offset((double)xofs, (double)yofs); sector_t * sector = P_PointInSector(pos); // The sector's floor is too high so spawn the flame elsewhere. if (sector->floorplane.ZatPoint(pos) > self->Z() + self->MaxStepHeight) { pos = self->Pos(); } AActor *drop = Spawn<APhosphorousFire> (DVector3(pos, self->Z() + 4.), ALLOW_REPLACE); if (drop != NULL) { drop->Vel.X = self->Vel.X + pr_phburn.Random2 (7); drop->Vel.Y = self->Vel.Y + pr_phburn.Random2 (7); drop->Vel.Z = self->Vel.Z - 1; drop->reactiontime = (pr_phburn() & 3) + 2; drop->flags |= MF_DROPPED; } } return 0; }
void A_DripBlood (AActor *actor) { AActor *mo; fixed_t x, y; x = actor->x + (pr_dripblood.Random2 () << 11); y = actor->y + (pr_dripblood.Random2 () << 11); mo = Spawn<ABlood> (x, y, actor->z); mo->momx = pr_dripblood.Random2 () << 10; mo->momy = pr_dripblood.Random2 () << 10; mo->flags2 |= MF2_LOGRAV; }
DEFINE_ACTION_FUNCTION(AActor, A_DripBlood) { PARAM_ACTION_PROLOGUE; AActor *mo; double xo = pr_dripblood.Random2() / 32.; double yo = pr_dripblood.Random2() / 32.; mo = Spawn ("Blood", self->Vec3Offset(xo, yo, 0.), ALLOW_REPLACE); mo->Vel.X = pr_dripblood.Random2 () / 64.; mo->Vel.Y = pr_dripblood.Random2() / 64.; mo->Gravity = 1./8; return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_PotteryExplode) { AActor *mo = NULL; int i; for(i = (pr_pottery()&3)+3; i; i--) { mo = Spawn ("PotteryBit", self->x, self->y, self->z, ALLOW_REPLACE); if (mo) { mo->SetState (mo->SpawnState + (pr_pottery()%5)); mo->velz = ((pr_pottery()&7)+5)*(3*FRACUNIT/4); mo->velx = (pr_pottery.Random2())<<(FRACBITS-6); mo->vely = (pr_pottery.Random2())<<(FRACBITS-6); } } S_Sound (mo, CHAN_BODY, "PotteryExplode", 1, ATTN_NORM); // Spawn an item? const PClass *type = P_GetSpawnableType(self->args[0]); if (type != NULL) { if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) || !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER)) { // Only spawn monsters if not -nomonsters Spawn (type, self->x, self->y, self->z, ALLOW_REPLACE); } } }
DEFINE_ACTION_FUNCTION(AActor, A_SoAExplode) { AActor *mo; int i; for (i = 0; i < 10; i++) { mo = Spawn ("ZArmorChunk", self->x+((pr_soaexplode()-128)<<12), self->y+((pr_soaexplode()-128)<<12), self->z+(pr_soaexplode()*self->height/256), ALLOW_REPLACE); if (mo) { mo->SetState (mo->SpawnState + i); mo->velz = ((pr_soaexplode()&7)+5)*FRACUNIT; mo->velx = pr_soaexplode.Random2()<<(FRACBITS-6); mo->vely = pr_soaexplode.Random2()<<(FRACBITS-6); } } // Spawn an item? const PClass *type = P_GetSpawnableType(self->args[0]); if (type != NULL) { if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) || !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER)) { // Only spawn monsters if not -nomonsters Spawn (type, self->x, self->y, self->z, ALLOW_REPLACE); } } S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_NORM); self->Destroy (); }
void AChickenPlayer::MorphPlayerThink () { if (health > 0) { // Handle beak movement P_UpdateBeak (this); } if (player->morphTics & 15) { return; } if (Vel.X == 0 && Vel.Y == 0 && pr_chickenplayerthink () < 160) { // Twitch view angle Angles.Yaw += pr_chickenplayerthink.Random2() * (360. / 256. / 32.); } if ((Z() <= floorz) && (pr_chickenplayerthink() < 32)) { // Jump and noise Vel.Z += JumpZ; FState * painstate = FindState(NAME_Pain); if (painstate != NULL) SetState (painstate); } if (pr_chickenplayerthink () < 48) { // Just noise S_Sound (this, CHAN_VOICE, "chicken/active", 1, ATTN_NORM); } }
DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer) { PARAM_ACTION_PROLOGUE; player_t *player = self->player; if (player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } player->mo->PlayAttacking2 (); } self->angle += pr_flamethrower.Random2() << 18; self = P_SpawnPlayerMissile (self, PClass::FindActor("FlameMissile")); if (self != NULL) { self->velz += 5*FRACUNIT; } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_Feathers) { PARAM_ACTION_PROLOGUE; int i; int count; AActor *mo; if (self->health > 0) { // Pain count = pr_feathers() < 32 ? 2 : 1; } else { // Death count = 5 + (pr_feathers()&3); } for (i = 0; i < count; i++) { mo = Spawn("Feather", self->PosPlusZ(20.), NO_REPLACE); mo->target = self; mo->Vel.X = pr_feathers.Random2() / 256.; mo->Vel.Y = pr_feathers.Random2() / 256.; mo->Vel.Z = 1. + pr_feathers() / 128.; mo->SetState (mo->SpawnState + (pr_feathers()&7)); } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_CPosAttack) { int angle; int bangle; int damage; int slope; if (!self->target) return; // [RH] Andy Baker's stealth monsters if (self->flags & MF_STEALTH) { self->visdir = 1; } S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); A_FaceTarget (self); bangle = self->angle; slope = P_AimLineAttack (self, bangle, MISSILERANGE); angle = bangle + (pr_cposattack.Random2() << 20); damage = ((pr_cposattack()%5)+1)*3; P_LineAttack (self, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff); }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireArrow) { PARAM_ACTION_PROLOGUE; PARAM_CLASS(ti, AActor); angle_t savedangle; if (self->player == NULL) return 0; AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } if (ti) { savedangle = self->angle; self->angle += pr_electric.Random2 () << (18 - self->player->mo->accuracy * 5 / 100); self->player->mo->PlayAttacking2 (); P_SpawnPlayerMissile (self, ti); self->angle = savedangle; S_Sound (self, CHAN_WEAPON, "weapons/xbowshoot", 1, ATTN_NORM); } return 0; }
// // A_PosAttack // DEFINE_ACTION_FUNCTION(AActor, A_PosAttack) { int angle; int damage; int slope; // [BC] Server takes care of the rest of this. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { S_Sound( self, CHAN_WEAPON, "grunt/attack", 1, ATTN_NORM ); return; } if (!self->target) return; A_FaceTarget (self); angle = self->angle; slope = P_AimLineAttack (self, angle, MISSILERANGE); S_Sound (self, CHAN_WEAPON, "grunt/attack", 1, ATTN_NORM); angle += pr_posattack.Random2() << 20; damage = ((pr_posattack()%5)+1)*3; P_LineAttack (self, angle, MISSILERANGE, slope, damage, NAME_None, NAME_BulletPuff); }
static void MarinePunch(AActor *self, int damagemul) { angle_t angle; int damage; int pitch; AActor *linetarget; 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, &linetarget); // turn to face target if (linetarget) { S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM); self->angle = self->AngleTo(linetarget); } }
DEFINE_ACTION_FUNCTION(AActor, A_JabDagger) { angle_t angle; int damage; int pitch; int power; AActor *linetarget; power = MIN(10, self->player->mo->stamina / 10); damage = (pr_jabdagger() % (power + 8)) * (power + 2); if (self->FindInventory<APowerStrength>()) { damage *= 10; } angle = self->angle + (pr_jabdagger.Random2() << 18); pitch = P_AimLineAttack (self, angle, 80*FRACUNIT, &linetarget); P_LineAttack (self, angle, 80*FRACUNIT, pitch, damage, NAME_Melee, "StrifeSpark", true, &linetarget); // turn to face target if (linetarget) { S_Sound (self, CHAN_WEAPON, linetarget->flags & MF_NOBLOOD ? "misc/metalhit" : "misc/meathit", 1, ATTN_NORM); self->angle = self->AngleTo(linetarget); self->flags |= MF_JUSTATTACKED; P_DaggerAlert (self, linetarget); } else { S_Sound (self, CHAN_WEAPON, "misc/swish", 1, ATTN_NORM); } }
// // A_FireShotgun2 // DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) { PARAM_ACTION_PROLOGUE; int i; DAngle angle; int damage; player_t *player; if (NULL == (player = self->player)) { return 0; } S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM); AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2)) return 0; P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash)); self->player->psprites[ps_flash].processPending = true; } player->mo->PlayAttacking2 (); DAngle pitch = P_BulletSlope (self); for (i=0 ; i<20 ; i++) { damage = 5*(pr_fireshotgun2()%3+1); angle = self->Angles.Yaw + pr_fireshotgun2.Random2() * (11.25 / 256); // Doom adjusts the bullet slope by shifting a random number [-255,255] // left 5 places. At 2048 units away, this means the vertical position // of the shot can deviate as much as 255 units from nominal. So using // some simple trigonometry, that means the vertical angle of the shot // can deviate by as many as ~7.097 degrees or ~84676099 BAMs. P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch + pr_fireshotgun2.Random2() * (7.097 / 256), damage, NAME_Hitscan, NAME_BulletPuff); } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_TossArm) { AActor *foo = Spawn("InquisitorArm", self->x, self->y, self->z + 24*FRACUNIT, ALLOW_REPLACE); foo->angle = self->angle - ANGLE_90 + (pr_inq.Random2() << 22); foo->velx = FixedMul (foo->Speed, finecosine[foo->angle >> ANGLETOFINESHIFT]) >> 3; foo->vely = FixedMul (foo->Speed, finesine[foo->angle >> ANGLETOFINESHIFT]) >> 3; foo->velz = pr_inq() << 10; }
void A_TossArm (AActor *self) { AActor *foo = Spawn<AInquisitorArm> (self->x, self->y, self->z + 24*FRACUNIT, ALLOW_REPLACE); foo->angle = self->angle - ANGLE_90 + (pr_inq.Random2() << 22); foo->momx = FixedMul (foo->Speed, finecosine[foo->angle >> ANGLETOFINESHIFT]) >> 3; foo->momy = FixedMul (foo->Speed, finesine[foo->angle >> ANGLETOFINESHIFT]) >> 3; foo->momz = pr_inq() << 10; }
DEFINE_ACTION_FUNCTION(AActor, A_Bang4Cloud) { fixed_t spawnx, spawny; spawnx = self->x + (pr_bang4cloud.Random2() & 3) * 10240; spawny = self->y + (pr_bang4cloud.Random2() & 3) * 10240; Spawn("Bang4Cloud", spawnx, spawny, self->z, ALLOW_REPLACE); }
DEFINE_ACTION_FUNCTION(AActor, A_BishopPainBlur) { AActor *mo; if (pr_pain() < 64) { self->SetState (self->FindState ("Blur")); return; } fixed_t xo = (pr_pain.Random2() << 12); fixed_t yo = (pr_pain.Random2() << 12); fixed_t zo = (pr_pain.Random2() << 11); mo = Spawn ("BishopPainBlur", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); if (mo) { mo->angle = self->angle; } }
DEFINE_ACTION_FUNCTION(AActor, A_SpawnProgrammerBase) { AActor *foo = Spawn("ProgrammerBase", self->PosPlusZ(24*FRACUNIT), ALLOW_REPLACE); if (foo != NULL) { foo->angle = self->angle + ANGLE_180 + (pr_prog.Random2() << 22); foo->velx = FixedMul (foo->Speed, finecosine[foo->angle >> ANGLETOFINESHIFT]); foo->vely = FixedMul (foo->Speed, finesine[foo->angle >> ANGLETOFINESHIFT]); foo->velz = pr_prog() << 9; }
DEFINE_ACTION_FUNCTION(AActor, A_TossArm) { PARAM_ACTION_PROLOGUE; AActor *foo = Spawn("InquisitorArm", self->PosPlusZ(24.), ALLOW_REPLACE); foo->Angles.Yaw = self->Angles.Yaw - 90. + pr_inq.Random2() * (360./1024.); foo->VelFromAngle(foo->Speed / 8); foo->Vel.Z = pr_inq() / 64.; return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2Pre) { S_Sound (self, CHAN_WEAPON, "weapons/mauler2charge", 1, ATTN_NORM); if (self->player != NULL) { self->player->psprites[ps_weapon].sx += pr_mauler2.Random2() << 10; self->player->psprites[ps_weapon].sy += pr_mauler2.Random2() << 10; } }
void A_ImpExplode (AActor *self) { AActor *chunk; self->flags &= ~MF_NOGRAVITY; chunk = Spawn<AHereticImpChunk1> (self->x, self->y, self->z, ALLOW_REPLACE); chunk->momx = pr_imp.Random2 () << 10; chunk->momy = pr_imp.Random2 () << 10; chunk->momz = 9*FRACUNIT; chunk = Spawn<AHereticImpChunk2> (self->x, self->y, self->z, ALLOW_REPLACE); chunk->momx = pr_imp.Random2 () << 10; chunk->momy = pr_imp.Random2 () << 10; chunk->momz = 9*FRACUNIT; if (self->special1 == 666) { // Extreme death crash self->SetState (&AHereticImp::States[S_IMP_XCRASH]); } }