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_FireAssaultGun) { PARAM_ACTION_PROLOGUE; bool accurate; S_Sound (self, CHAN_WEAPON, "weapons/assaultgun", 1, ATTN_NORM); if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } self->player->mo->PlayAttacking2 (); accurate = !self->player->refire; } else { accurate = true; } P_StrifeGunShot (self, accurate, P_BulletSlope (self)); return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_FHammerThrow) { AActor *mo; player_t *player; if (NULL == (player = self->player)) { return; } if (!player->mo->special1) { return; } AWeapon *weapon = player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire, false)) return; } mo = P_SpawnPlayerMissile (player->mo, PClass::FindClass ("HammerMissile")); if (mo) { mo->special1 = 0; } }
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_FirePistol // DEFINE_ACTION_FUNCTION(AActor, A_FirePistol) { PARAM_ACTION_PROLOGUE; bool accurate; if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return 0; P_SetPsprite (self->player, ps_flash, weapon->FindState(NAME_Flash)); } self->player->mo->PlayAttacking2 (); accurate = !self->player->refire; } else { accurate = true; } S_Sound (self, CHAN_WEAPON, "weapons/pistol", 1, ATTN_NORM); P_GunShot (self, accurate, PClass::FindActor(NAME_BulletPuff), P_BulletSlope (self)); return 0; }
// // A_FireShotgun // DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun) { PARAM_ACTION_PROLOGUE; int i; player_t *player; if (NULL == (player = self->player)) { return 0; } S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM); AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) 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 < 7; i++) { P_GunShot (self, false, PClass::FindActor(NAME_BulletPuff), pitch); } return 0; }
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_FireConePL1) { PARAM_ACTION_PROLOGUE; angle_t angle; int damage; int slope; int i; AActor *mo; bool conedone=false; player_t *player; AActor *linetarget; if (NULL == (player = self->player)) { return 0; } AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } S_Sound (self, CHAN_WEAPON, "MageShardsFire", 1, ATTN_NORM); damage = 90+(pr_cone()&15); for (i = 0; i < 16; i++) { angle = self->angle+i*(ANG45/16); slope = P_AimLineAttack (self, angle, MELEERANGE, &linetarget, 0, ALF_CHECK3D); if (linetarget) { P_DamageMobj (linetarget, self, self, damage, NAME_Ice); conedone = true; break; } } // didn't find any creatures, so fire projectiles if (!conedone) { mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(AFrostMissile)); if (mo) { mo->special1 = SHARDSPAWN_LEFT|SHARDSPAWN_DOWN|SHARDSPAWN_UP |SHARDSPAWN_RIGHT; mo->special2 = 3; // Set sperm count (levels of reproductivity) mo->target = self; mo->args[0] = 3; // Mark Initial shard as super damage } } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_FHammerThrow) { AActor *mo; player_t *player; if (NULL == (player = self->player)) { return; } if (!player->mo->special1) { return; } AWeapon *weapon = player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire, false)) return; } // [BC] Weapons are handled by the server. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } mo = P_SpawnPlayerMissile (player->mo, PClass::FindClass ("HammerMissile")); if (mo) { mo->special1 = 0; } // [BC] Apply spread. if ( player->cheats & CF_SPREAD ) { mo = P_SpawnPlayerMissile( player->mo, PClass::FindClass ("HammerMissile"), self->angle + ( ANGLE_45 / 3 )); if ( mo ) { mo->special1 = 0; } mo = P_SpawnPlayerMissile( player->mo, PClass::FindClass ("HammerMissile"), self->angle - ( ANGLE_45 / 3 )); if ( mo ) { mo->special1 = 0; } } }
DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2) { if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } self->player->mo->PlayAttacking2 (); } P_SpawnPlayerMissile (self, PClass::FindClass("MaulerTorpedo")); P_DamageMobj (self, self, NULL, 20, self->DamageType); P_ThrustMobj (self, self->angle + ANGLE_180, 0x7D000); }
// // 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_PARAMS(AActor, A_FireGrenade) { PARAM_ACTION_PROLOGUE; PARAM_CLASS(grenadetype, AActor); PARAM_ANGLE(angleofs); PARAM_STATE(flash) player_t *player = self->player; AActor *grenade; DAngle an; AWeapon *weapon; if (player == nullptr || grenadetype == nullptr) return 0; if ((weapon = player->ReadyWeapon) == nullptr) return 0; if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; P_SetPsprite (player, PSP_FLASH, flash, true); if (grenadetype != nullptr) { self->AddZ(32); grenade = P_SpawnSubMissile (self, grenadetype, self); self->AddZ(-32); if (grenade == nullptr) return 0; if (grenade->SeeSound != 0) { S_Sound (grenade, CHAN_VOICE, grenade->SeeSound, 1, ATTN_NORM); } grenade->Vel.Z = (-self->Angles.Pitch.TanClamped()) * grenade->Speed + 8; DVector2 offset = self->Angles.Yaw.ToVector(self->radius + grenade->radius); DAngle an = self->Angles.Yaw + angleofs; offset += an.ToVector(15); grenade->SetOrigin(grenade->Vec3Offset(offset.X, offset.Y, 0.), false); } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2) { PARAM_ACTION_PROLOGUE; if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } self->player->mo->PlayAttacking2 (); } P_SpawnPlayerMissile (self, PClass::FindActor("MaulerTorpedo")); P_DamageMobj (self, self, NULL, 20, self->DamageType); self->Thrust(self->Angles.Yaw+180., 7.8125); return 0; }
// // A_FireMissile // DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) { PARAM_ACTION_PROLOGUE; player_t *player; if (NULL == (player = self->player)) { return 0; } AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return 0; } P_SpawnPlayerMissile (self, PClass::FindActor("Rocket")); return 0; }
// // A_FireCGun // DEFINE_ACTION_FUNCTION(AActor, A_FireCGun) { PARAM_ACTION_PROLOGUE; player_t *player; if (self == NULL || NULL == (player = self->player)) { return 0; } AWeapon *weapon = player->ReadyWeapon; if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return 0; S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM); FState *flash = weapon->FindState(NAME_Flash); if (flash != NULL) { // [RH] Fix for Sparky's messed-up Dehacked patch! Blargh! FState * atk = weapon->FindState(NAME_Fire); int theflash = clamp (int(player->psprites[ps_weapon].state - atk), 0, 1); if (flash[theflash].sprite != flash->sprite) { theflash = 0; } P_SetSafeFlash (weapon, player, flash, theflash); } } player->mo->PlayAttacking2 (); P_GunShot (self, !player->refire, PClass::FindActor(NAME_BulletPuff), P_BulletSlope (self)); return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile) { player_t *player = self->player; angle_t savedangle; if (self->player == NULL) return; AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } savedangle = self->angle; self->angle += pr_minimissile.Random2() << (19 - player->mo->accuracy * 5 / 100); player->mo->PlayAttacking2 (); P_SpawnPlayerMissile (self, PClass::FindClass("MiniMissile")); self->angle = savedangle; }
// // A_Punch // DEFINE_ACTION_FUNCTION(AActor, A_Punch) { PARAM_ACTION_PROLOGUE; angle_t angle; int damage; int pitch; AActor *linetarget; if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } } damage = (pr_punch()%10+1)<<1; if (self->FindInventory<APowerStrength>()) damage *= 10; angle = self->angle; angle += pr_punch.Random2() << 18; pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget); P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, LAF_ISMELEEATTACK, &linetarget); // turn to face target if (linetarget) { S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM); self->angle = self->AngleTo(linetarget); } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_CFlameAttack) { player_t *player; if (NULL == (player = self->player)) { return; } AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } // [BC] Weapons are handled by the server. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { S_Sound (self, CHAN_WEAPON, "ClericFlameFire", 1, ATTN_NORM); return; } P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACFlameMissile)); // [BC] Apply spread. if ( player->cheats & CF_SPREAD ) { P_SpawnPlayerMissile( self, RUNTIME_CLASS(ACFlameMissile), self->angle + ( ANGLE_45 / 3 )); P_SpawnPlayerMissile( self, RUNTIME_CLASS(ACFlameMissile), self->angle - ( ANGLE_45 / 3 )); } S_Sound (self, CHAN_WEAPON, "ClericFlameFire", 1, ATTN_NORM); // [BC] If we're the server, tell other clients to make the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_WeaponSound( ULONG( player - players ), "ClericFlameFire", ULONG( player - players ), SVCF_SKIPTHISCLIENT ); }
DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile) { PARAM_ACTION_PROLOGUE; player_t *player = self->player; DAngle savedangle; if (self->player == NULL) return 0; AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } savedangle = self->Angles.Yaw; self->Angles.Yaw += pr_minimissile.Random2() * (11.25 / 256) * player->mo->AccuracyFactor(); player->mo->PlayAttacking2 (); P_SpawnPlayerMissile (self, PClass::FindActor("MiniMissile")); self->Angles.Yaw = savedangle; return 0; }
void A_FAxeAttack (AActor *actor) { angle_t angle; fixed_t power; int damage; int slope; int i; int useMana; player_t *player; AWeapon *weapon; const TypeInfo *pufftype; if (NULL == (player = actor->player)) { return; } AActor *pmo=player->mo; damage = 40+(pr_atk()&15); damage += pr_atk()&7; power = 0; weapon = player->ReadyWeapon; if (player->ReadyWeapon->Ammo1->Amount > 0) { damage <<= 1; power = 6*FRACUNIT; pufftype = RUNTIME_CLASS(AAxePuffGlow); useMana = 1; } else { pufftype = RUNTIME_CLASS(AAxePuff); useMana = 0; } for (i = 0; i < 16; i++) { angle = pmo->angle+i*(ANG45/16); slope = P_AimLineAttack (pmo, angle, AXERANGE); if (linetarget) { P_LineAttack (pmo, angle, AXERANGE, slope, damage, MOD_HIT, pufftype); if (linetarget->flags3&MF3_ISMONSTER || linetarget->player) { P_ThrustMobj (linetarget, angle, power); } AdjustPlayerAngle (pmo); useMana++; goto axedone; } angle = pmo->angle-i*(ANG45/16); slope = P_AimLineAttack (pmo, angle, AXERANGE); if (linetarget) { P_LineAttack (pmo, angle, AXERANGE, slope, damage, MOD_HIT, pufftype); if (linetarget->flags3&MF3_ISMONSTER) { P_ThrustMobj (linetarget, angle, power); } AdjustPlayerAngle (pmo); useMana++; goto axedone; } } // didn't find any creatures, so try to strike any walls pmo->special1 = 0; angle = pmo->angle; slope = P_AimLineAttack (pmo, angle, MELEERANGE); P_LineAttack (pmo, angle, MELEERANGE, slope, damage, MOD_HIT, pufftype); axedone: if (useMana == 2) { AWeapon *weapon = player->ReadyWeapon; if (weapon != NULL) { weapon->DepleteAmmo (weapon->bAltFire, false); if ((weapon->Ammo1 == NULL || weapon->Ammo1->Amount == 0) && (!(weapon->WeaponFlags & WIF_PRIMARY_USES_BOTH) || weapon->Ammo2 == NULL || weapon->Ammo2->Amount == 0)) { P_SetPsprite (player, ps_weapon, &AFWeapAxe::States[S_FAXEATK+5]); } } } return; }
DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1) { angle_t angle; int damage; int slope; int i; AActor *mo; bool conedone=false; player_t *player; AActor *linetarget; if (NULL == (player = self->player)) { return; } AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } S_Sound (self, CHAN_WEAPON, "MageShardsFire", 1, ATTN_NORM); // [BC] Weapons are handled by the server. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } // [BC] If we're the server, play the sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_WeaponSound( ULONG( player - players ), "MageShardsFire", ULONG( player - players ), SVCF_SKIPTHISCLIENT ); damage = 90+(pr_cone()&15); for (i = 0; i < 16; i++) { angle = self->angle+i*(ANG45/16); slope = P_AimLineAttack (self, angle, MELEERANGE, &linetarget, 0, false, true); if (linetarget) { P_DamageMobj (linetarget, self, self, damage, NAME_Ice); // [BC] Apply spread. if ( player->cheats & CF_SPREAD ) P_DamageMobj (linetarget, self, self, damage * 2, NAME_Ice); conedone = true; break; } } // didn't find any creatures, so fire projectiles if (!conedone) { mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(AFrostMissile)); if (mo) { mo->special1 = SHARDSPAWN_LEFT|SHARDSPAWN_DOWN|SHARDSPAWN_UP |SHARDSPAWN_RIGHT; mo->special2 = 3; // Set sperm count (levels of reproductivity) mo->target = self; mo->args[0] = 3; // Mark Initial shard as super damage } // [BC] Apply spread. if ( player->cheats & CF_SPREAD ) { mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(AFrostMissile), self->angle + ( ANGLE_45 / 3 )); if (mo) { mo->special1 = SHARDSPAWN_LEFT|SHARDSPAWN_DOWN|SHARDSPAWN_UP |SHARDSPAWN_RIGHT; mo->special2 = 3; // Set sperm count (levels of reproductivity) mo->target = self; mo->args[0] = 3; // Mark Initial shard as super damage } mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(AFrostMissile), self->angle - ( ANGLE_45 / 3 )); if (mo) { mo->special1 = SHARDSPAWN_LEFT|SHARDSPAWN_DOWN|SHARDSPAWN_UP |SHARDSPAWN_RIGHT; mo->special2 = 3; // Set sperm count (levels of reproductivity) mo->target = self; mo->args[0] = 3; // Mark Initial shard as super damage } } } }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) { 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; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_FLOAT_OPT (range) { range = 0; } PARAM_ANGLE_OPT (spread_xy) { spread_xy = 2.8125; } PARAM_ANGLE_OPT (spread_z) { spread_z = 0.; } PARAM_FLOAT_OPT (lifesteal) { lifesteal = 0; } PARAM_INT_OPT (lifestealmax) { lifestealmax = 0; } PARAM_CLASS_OPT (armorbonustype, ABasicArmorBonus) { armorbonustype = NULL; } DAngle angle; DAngle slope; player_t *player; FTranslatedLineTarget t; int actualdamage; if (NULL == (player = self->player)) { return 0; } if (pufftype == NULL) { pufftype = PClass::FindActor(NAME_BulletPuff); } if (damage == 0) { damage = 2; } if (!(flags & SF_NORANDOM)) { damage *= (pr_saw()%10+1); } if (range == 0) { range = SAWRANGE; } angle = self->Angles.Yaw + spread_xy * (pr_saw.Random2() / 255.); slope = P_AimLineAttack (self, angle, range, &t) + spread_z * (pr_saw.Random2() / 255.); AWeapon *weapon = self->player->ReadyWeapon; if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!t.linetarget && (flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } P_LineAttack (self, angle, range, slope, damage, NAME_Melee, pufftype, false, &t, &actualdamage); if (!t.linetarget) { if ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64)) { player->extralight = !player->extralight; } S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); return 0; } if (flags & SF_RANDOMLIGHTHIT) { int randVal = pr_saw(); if (randVal < 64) { player->extralight = 0; } else if (randVal < 160) { player->extralight = 1; } else { player->extralight = 2; } } if (lifesteal && !(t.linetarget->flags5 & MF5_DONTDRAIN)) { if (flags & SF_STEALARMOR) { if (armorbonustype == NULL) { armorbonustype = dyn_cast<ABasicArmorBonus::MetaClass>(PClass::FindClass("ArmorBonus")); } if (armorbonustype != NULL) { assert(armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))); ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn(armorbonustype)); armorbonus->SaveAmount = int(armorbonus->SaveAmount * actualdamage * lifesteal); armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax; armorbonus->flags |= MF_DROPPED; armorbonus->ClearCounters(); if (!armorbonus->CallTryPickup (self)) { armorbonus->Destroy (); } } } else { P_GiveBody (self, int(actualdamage * lifesteal), lifestealmax); } } S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM); // turn to face target if (!(flags & SF_NOTURN)) { DAngle anglediff = deltaangle(self->Angles.Yaw, t.angleFromSource); if (anglediff < 0.0) { if (anglediff < -4.5) self->Angles.Yaw = angle + 90.0 / 21; else self->Angles.Yaw -= 4.5; } else { if (anglediff > 4.5) self->Angles.Yaw = angle - 90.0 / 21; else self->Angles.Yaw += 4.5; } } if (!(flags & SF_NOPULLIN)) self->flags |= MF_JUSTATTACKED; return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack) { angle_t angle; fixed_t power; int damage; int slope; int i; int useMana; player_t *player; AWeapon *weapon; const PClass *pufftype; AActor *linetarget; if (NULL == (player = self->player)) { return; } AActor *pmo=player->mo; damage = 40+(pr_axeatk()&15); damage += pr_axeatk()&7; power = 0; weapon = player->ReadyWeapon; if (player->ReadyWeapon->Ammo1->Amount > 0) { damage <<= 1; power = 6*FRACUNIT; pufftype = PClass::FindClass ("AxePuffGlow"); useMana = 1; } else { pufftype = PClass::FindClass ("AxePuff"); useMana = 0; } for (i = 0; i < 16; i++) { angle = pmo->angle+i*(ANG45/16); slope = P_AimLineAttack (pmo, angle, AXERANGE, &linetarget); if (linetarget) { P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget); if (linetarget != NULL) { if (linetarget->flags3&MF3_ISMONSTER || linetarget->player) { P_ThrustMobj (linetarget, angle, power); } AdjustPlayerAngle (pmo, linetarget); useMana++; goto axedone; } } angle = pmo->angle-i*(ANG45/16); slope = P_AimLineAttack (pmo, angle, AXERANGE, &linetarget); if (linetarget) { P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget); if (linetarget != NULL) { if (linetarget->flags3&MF3_ISMONSTER) { P_ThrustMobj (linetarget, angle, power); } AdjustPlayerAngle (pmo, linetarget); useMana++; goto axedone; } } } // didn't find any creatures, so try to strike any walls pmo->special1 = 0; angle = pmo->angle; slope = P_AimLineAttack (pmo, angle, MELEERANGE, &linetarget); P_LineAttack (pmo, angle, MELEERANGE, slope, damage, NAME_Melee, pufftype, true); axedone: if (useMana == 2) { AWeapon *weapon = player->ReadyWeapon; if (weapon != NULL) { weapon->DepleteAmmo (weapon->bAltFire, false); if ((weapon->Ammo1 == NULL || weapon->Ammo1->Amount == 0) && (!(weapon->WeaponFlags & WIF_PRIMARY_USES_BOTH) || weapon->Ammo2 == NULL || weapon->Ammo2->Amount == 0)) { P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("Fire") + 5); } } } return; }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) { angle_t angle; angle_t slope; player_t *player; AActor *linetarget; int actualdamage; ACTION_PARAM_START(11); ACTION_PARAM_SOUND(fullsound, 0); ACTION_PARAM_SOUND(hitsound, 1); ACTION_PARAM_INT(damage, 2); ACTION_PARAM_CLASS(pufftype, 3); ACTION_PARAM_INT(Flags, 4); ACTION_PARAM_FIXED(Range, 5); ACTION_PARAM_ANGLE(Spread_XY, 6); ACTION_PARAM_ANGLE(Spread_Z, 7); ACTION_PARAM_FIXED(LifeSteal, 8); ACTION_PARAM_INT(lifestealmax, 9); ACTION_PARAM_CLASS(armorbonustype, 10); if (NULL == (player = self->player)) { return; } if (pufftype == NULL) pufftype = PClass::FindClass(NAME_BulletPuff); if (damage == 0) damage = 2; if (!(Flags & SF_NORANDOM)) damage *= (pr_saw()%10+1); // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states) if (Range == 0) Range = MELEERANGE+1; angle = self->angle + (pr_saw.Random2() * (Spread_XY / 255)); slope = P_AimLineAttack (self, angle, Range, &linetarget) + (pr_saw.Random2() * (Spread_Z / 255)); AWeapon *weapon = self->player->ReadyWeapon; if ((weapon != NULL) && !(Flags & SF_NOUSEAMMO) && !(!linetarget && (Flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO)) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } P_LineAttack (self, angle, Range, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage); if (!linetarget) { if ((Flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64)) { player->extralight = !player->extralight; } S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); return; } if (Flags & SF_RANDOMLIGHTHIT) { int randVal = pr_saw(); if (randVal < 64) { player->extralight = 0; } else if (randVal < 160) { player->extralight = 1; } else { player->extralight = 2; } } if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN)) { if (Flags & SF_STEALARMOR) { if (!armorbonustype) armorbonustype = PClass::FindClass("ArmorBonus"); if (armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))) { ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn (armorbonustype, 0,0,0, NO_REPLACE)); armorbonus->SaveAmount *= (actualdamage * LifeSteal) >> FRACBITS; armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax; armorbonus->flags |= MF_DROPPED; armorbonus->ClearCounters(); if (!armorbonus->CallTryPickup (self)) { armorbonus->Destroy (); } } } else {
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) { 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; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_FIXED_OPT (range) { range = 0; } PARAM_ANGLE_OPT(spread_xy) { spread_xy = 33554432; /*angle_t(2.8125 * (ANGLE_90 / 90.0));*/ } // The floating point expression does not get optimized away. PARAM_ANGLE_OPT (spread_z) { spread_z = 0; } PARAM_FIXED_OPT (lifesteal) { lifesteal = 0; } PARAM_INT_OPT (lifestealmax) { lifestealmax = 0; } PARAM_CLASS_OPT (armorbonustype, ABasicArmorBonus) { armorbonustype = NULL; } angle_t angle; angle_t slope; player_t *player; AActor *linetarget; int actualdamage; if (NULL == (player = self->player)) { return 0; } if (pufftype == NULL) { pufftype = PClass::FindActor(NAME_BulletPuff); } if (damage == 0) { damage = 2; } if (!(flags & SF_NORANDOM)) { damage *= (pr_saw()%10+1); } if (range == 0) { // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states) range = MELEERANGE+1; } angle = self->angle + (pr_saw.Random2() * (spread_xy / 255)); slope = P_AimLineAttack (self, angle, range, &linetarget) + (pr_saw.Random2() * (spread_z / 255)); AWeapon *weapon = self->player->ReadyWeapon; if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!linetarget && (flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } P_LineAttack (self, angle, range, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage); if (!linetarget) { if ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64)) { player->extralight = !player->extralight; } S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); return 0; } if (flags & SF_RANDOMLIGHTHIT) { int randVal = pr_saw(); if (randVal < 64) { player->extralight = 0; } else if (randVal < 160) { player->extralight = 1; } else { player->extralight = 2; } } if (lifesteal && !(linetarget->flags5 & MF5_DONTDRAIN)) { if (flags & SF_STEALARMOR) { if (armorbonustype == NULL) { armorbonustype = dyn_cast<ABasicArmorBonus::MetaClass>(PClass::FindClass("ArmorBonus")); } if (armorbonustype != NULL) { assert(armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))); ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn(armorbonustype, 0,0,0, NO_REPLACE)); armorbonus->SaveAmount *= (actualdamage * lifesteal) >> FRACBITS; armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax; armorbonus->flags |= MF_DROPPED; armorbonus->ClearCounters(); if (!armorbonus->CallTryPickup (self)) { armorbonus->Destroy (); } } } else {