DEFINE_ACTION_FUNCTION(AActor, A_FireAssaultGun) { 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; } self->player->mo->PlayAttacking2 (); accurate = !self->player->refire; } else { accurate = true; } P_StrifeGunShot (self, accurate, P_BulletSlope (self)); }
void P_ReloadWeapon (player_t *player, FState *state) { AWeapon *weapon; if (player->Bot == NULL && bot_observer) { return; } weapon = player->ReadyWeapon; if (weapon == NULL) { return; } if (state == NULL) { state = weapon->GetRelState(); } // [XA] don't change state if still null, so if the modder sets // WRF_RELOAD to true but forgets to define the Reload state, the weapon // won't disappear. ;) if (state != NULL) P_SetPsprite (player, ps_weapon, state); }
AWeapon *FWeaponSlot::PickWeapon(player_t *player, bool checkammo) { int i, j; if (player->mo == NULL) { return NULL; } // Does this slot even have any weapons? if (Weapons.Size() == 0) { return player->ReadyWeapon; } if (player->ReadyWeapon != NULL) { for (i = 0; (unsigned)i < Weapons.Size(); i++) { if (Weapons[i].Type == player->ReadyWeapon->GetClass() || (player->ReadyWeapon->WeaponFlags & WIF_POWERED_UP && player->ReadyWeapon->SisterWeapon != NULL && player->ReadyWeapon->SisterWeapon->GetClass() == Weapons[i].Type)) { for (j = (i == 0 ? Weapons.Size() - 1 : i - 1); j != i; j = (j == 0 ? Weapons.Size() - 1 : j - 1)) { AWeapon *weap = static_cast<AWeapon *> (player->mo->FindInventory(Weapons[j].Type)); if (weap != NULL && weap->IsKindOf(RUNTIME_CLASS(AWeapon))) { if (!checkammo || weap->CheckAmmo(AWeapon::EitherFire, false)) { return weap; } } } } } } for (i = Weapons.Size() - 1; i >= 0; i--) { AWeapon *weap = static_cast<AWeapon *> (player->mo->FindInventory(Weapons[i].Type)); if (weap != NULL && weap->IsKindOf(RUNTIME_CLASS(AWeapon))) { if (!checkammo || weap->CheckAmmo(AWeapon::EitherFire, false)) { return weap; } } } return player->ReadyWeapon; }
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 {
bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, bool force) { AWeapon *beastweap; APlayerPawn *mo; APlayerPawn *pmo; angle_t angle; pmo = player->mo; // [MH] // Checks pmo as well; the PowerMorph destroyer will // try to unmorph the player; if the destroyer runs // because the level or game is ended while morphed, // by the time it gets executed the morphed player // pawn instance may have already been destroyed. if (pmo == NULL || pmo->tracer == NULL) { return false; } bool DeliberateUnmorphIsOkay = !!(MORPH_STANDARDUNDOING & unmorphflag); if ((pmo->flags2 & MF2_INVULNERABLE) // If the player is invulnerable && ((player != activator) // and either did not decide to unmorph, || (!((player->MorphStyle & MORPH_WHENINVULNERABLE) // or the morph style does not allow it || (DeliberateUnmorphIsOkay))))) // (but standard morph styles always allow it), { // Then the player is immune to the unmorph. return false; } mo = barrier_cast<APlayerPawn *>(pmo->tracer); mo->SetOrigin (pmo->Pos(), false); mo->flags |= MF_SOLID; pmo->flags &= ~MF_SOLID; if (!force && !P_TestMobjLocation (mo)) { // Didn't fit mo->flags &= ~MF_SOLID; pmo->flags |= MF_SOLID; player->morphTics = 2*TICRATE; return false; } pmo->player = NULL; // Remove the morph power if the morph is being undone prematurely. for (AInventory *item = pmo->Inventory, *next = NULL; item != NULL; item = next) { next = item->Inventory; if (item->IsKindOf(RUNTIME_CLASS(APowerMorph))) { static_cast<APowerMorph *>(item)->SetNoCallUndoMorph(); item->Destroy(); } } EndAllPowerupEffects(pmo->Inventory); mo->ObtainInventory (pmo); DObject::StaticPointerSubstitution (pmo, mo); if ((pmo->tid != 0) && (player->MorphStyle & MORPH_NEWTIDBEHAVIOUR)) { mo->tid = pmo->tid; mo->AddToHash (); } mo->angle = pmo->angle; mo->player = player; mo->reactiontime = 18; mo->flags = ActorFlags::FromInt (pmo->special2) & ~MF_JUSTHIT; mo->velx = 0; mo->vely = 0; player->velx = 0; player->vely = 0; mo->velz = pmo->velz; if (!(pmo->special2 & MF_JUSTHIT)) { mo->renderflags &= ~RF_INVISIBLE; } mo->flags = (mo->flags & ~(MF_SHADOW|MF_NOGRAVITY)) | (pmo->flags & (MF_SHADOW|MF_NOGRAVITY)); mo->flags2 = (mo->flags2 & ~MF2_FLY) | (pmo->flags2 & MF2_FLY); mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST); mo->Score = pmo->Score; InitAllPowerupEffects(mo->Inventory); PClassActor *exit_flash = player->MorphExitFlash; bool correctweapon = !!(player->MorphStyle & MORPH_LOSEACTUALWEAPON); bool undobydeathsaves = !!(player->MorphStyle & MORPH_UNDOBYDEATHSAVES); player->morphTics = 0; player->MorphedPlayerClass = 0; player->MorphStyle = 0; player->MorphExitFlash = NULL; player->viewheight = mo->ViewHeight; AInventory *level2 = mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2), true); if (level2 != NULL) { level2->Destroy (); } if ((player->health > 0) || undobydeathsaves) { player->health = mo->health = mo->SpawnHealth(); } else // killed when morphed so stay dead { mo->health = player->health; } player->mo = mo; if (player->camera == pmo) { player->camera = mo; } // [MH] // If the player that was morphed is the one // taking events, reset up the face, if any; // this is only needed for old-skool skins // and for the original DOOM status bar. if (player == &players[consoleplayer]) { FString face = pmo->GetClass()->Face; if (face.IsNotEmpty() && strcmp(face, "None") != 0) { // Assume root-level base skin to begin with size_t skinindex = 0; // If a custom skin was in use, then reload it // or else the base skin for the player class. if ((unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () && (size_t)player->userinfo.GetSkin() < numskins) { skinindex = player->userinfo.GetSkin(); } else if (PlayerClasses.Size () > 1) { const PClass *whatami = player->mo->GetClass(); for (unsigned int i = 0; i < PlayerClasses.Size (); ++i) { if (PlayerClasses[i].Type == whatami) { skinindex = i; break; } } } } } angle = mo->angle >> ANGLETOFINESHIFT; AActor *eflash = NULL; if (exit_flash != NULL) { eflash = Spawn(exit_flash, pmo->Vec3Offset(20*finecosine[angle], 20*finesine[angle], TELEFOGHEIGHT), ALLOW_REPLACE); if (eflash) eflash->target = mo; } mo->SetupWeaponSlots(); // Use original class's weapon slots. beastweap = player->ReadyWeapon; if (player->PremorphWeapon != NULL) { player->PremorphWeapon->PostMorphWeapon (); } else { player->ReadyWeapon = player->PendingWeapon = NULL; } if (correctweapon) { // Better "lose morphed weapon" semantics PClassActor *morphweapon = PClass::FindActor(pmo->MorphWeapon); if (morphweapon != NULL && morphweapon->IsDescendantOf(RUNTIME_CLASS(AWeapon))) { AWeapon *OriginalMorphWeapon = static_cast<AWeapon *>(mo->FindInventory (morphweapon)); if ((OriginalMorphWeapon != NULL) && (OriginalMorphWeapon->GivenAsMorphWeapon)) { // You don't get to keep your morphed weapon. if (OriginalMorphWeapon->SisterWeapon != NULL) { OriginalMorphWeapon->SisterWeapon->Destroy (); } OriginalMorphWeapon->Destroy (); } } } else // old behaviour (not really useful now) { // Assumptions made here are no longer valid if (beastweap != NULL) { // You don't get to keep your morphed weapon. if (beastweap->SisterWeapon != NULL) { beastweap->SisterWeapon->Destroy (); } beastweap->Destroy (); } } pmo->tracer = NULL; pmo->Destroy (); // Restore playerclass armor to its normal amount. AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>(); if (hxarmor != NULL) { hxarmor->Slots[4] = mo->GetClass()->HexenArmor[0]; } return true; }
static bool DoSubstitution (FString &out, const char *in) { player_t *player = &players[consoleplayer]; AWeapon *weapon = player->ReadyWeapon; const char *a, *b; a = in; out = ""; while ( (b = strchr(a, '$')) ) { out.AppendCStrPart(a, b - a); a = ++b; while (*b && isalpha(*b)) { ++b; } ptrdiff_t len = b - a; if (len == 6) { if (strnicmp(a, "health", 6) == 0) { out.AppendFormat("%d", player->health); } else if (strnicmp(a, "weapon", 6) == 0) { if (weapon == NULL) { out += "no weapon"; } else { out += weapon->GetClass()->TypeName; } } } else if (len == 5) { if (strnicmp(a, "armor", 5) == 0) { AInventory *armor = player->mo->FindInventory<ABasicArmor>(); out.AppendFormat("%d", armor != NULL ? armor->Amount : 0); } } else if (len == 9) { if (strnicmp(a, "ammocount", 9) == 0) { if (weapon == NULL) { out += '0'; } else { out.AppendFormat("%d", weapon->Ammo1 != NULL ? weapon->Ammo1->Amount : 0); if (weapon->Ammo2 != NULL) { out.AppendFormat("/%d", weapon->Ammo2->Amount); } } } } else if (len == 4) { if (strnicmp(a, "ammo", 4) == 0) { if (weapon == NULL || weapon->Ammo1 == NULL) { out += "no ammo"; } else { out.AppendFormat("%s", weapon->Ammo1->GetClass()->TypeName.GetChars()); if (weapon->Ammo2 != NULL) { out.AppendFormat("/%s", weapon->Ammo2->GetClass()->TypeName.GetChars()); } } } } else if (len == 0) { out += '$'; if (*b == '$') { b++; } } else { out += '$'; out.AppendCStrPart(a, len); } a = b; } // Return false if no substitution was performed if (a == in) { return false; } out += a; return true; }
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; }
//***************************************************************************** // // [CW] void chat_DoSubstitution( FString &Input ) { player_t *pPlayer = &players[consoleplayer]; AWeapon *pReadyWeapon = pPlayer->ReadyWeapon; if ( chat_substitution ) { FString Output; const char *pszString = Input.GetChars( ); for ( ; *pszString != 0; pszString++ ) { if ( !strncmp( pszString, "$ammocount", 10 )) { if ( pReadyWeapon && pReadyWeapon->Ammo1 ) { Output.AppendFormat( "%d", pReadyWeapon->Ammo1->Amount ); if ( pReadyWeapon->Ammo2 ) Output.AppendFormat( "/%d", pReadyWeapon->Ammo2->Amount ); } else { Output.AppendFormat( "no ammo" ); } pszString += 9; } else if ( !strncmp( pszString, "$ammo", 5 )) { if ( pReadyWeapon && pReadyWeapon->Ammo1 ) { Output.AppendFormat( "%s", pReadyWeapon->Ammo1->GetClass( )->TypeName.GetChars( ) ); if ( pReadyWeapon->Ammo2 ) { Output.AppendFormat( "/%s", pReadyWeapon->Ammo2->GetClass( )->TypeName.GetChars( )); } } else { Output.AppendFormat( "no ammo" ); } pszString += 4; } else if ( !strncmp( pszString, "$armor", 6 )) { AInventory *pArmor = pPlayer->mo->FindInventory<ABasicArmor>( ); int iArmorCount = 0; if ( pArmor ) iArmorCount = pArmor->Amount; Output.AppendFormat( "%d", iArmorCount ); pszString += 5; } else if ( !strncmp( pszString, "$health", 7 )) { Output.AppendFormat ("%d", pPlayer->health); pszString += 6; } else if ( !strncmp( pszString, "$weapon", 7 )) { if ( pReadyWeapon ) Output.AppendFormat( "%s", pReadyWeapon->GetClass( )->TypeName.GetChars( ) ); else Output.AppendFormat( "no weapon" ); pszString += 6; } else if ( !strncmp( pszString, "$location", 9 )) { Output += SECTINFO_GetPlayerLocation( consoleplayer ); pszString += 8; } else { Output.AppendCStrPart( pszString, 1 ); } } Input = Output; } }
static bool DoSubstitution (char *out, const char *in) { player_t *player = &players[consoleplayer]; AWeapon *weapon = player->ReadyWeapon; const char *a, *b; a = in; while ((b = strchr (a, '$'))) { strncpy (out, a, b - a); out += b - a; a = ++b; while (*b && isalpha (*b)) { ++b; } ptrdiff_t len = b - a; if (len == 6) { if (strnicmp (a, "health", 6) == 0) { out += sprintf (out, "%d", player->health); } else if (strnicmp (a, "weapon", 6) == 0) { if (weapon == NULL) { out += sprintf (out, "no weapon"); } else { out += sprintf (out, "%s", weapon->GetClass()->Name+1); } } } else if (len == 5) { if (strnicmp (a, "armor", 5) == 0) { AInventory *armor = player->mo->FindInventory<ABasicArmor>(); int armorpoints = armor != NULL ? armor->Amount : 0; out += sprintf (out, "%d", armorpoints); } } else if (len == 9) { if (strnicmp (a, "ammocount", 9) == 0) { if (weapon == NULL) { out += sprintf (out, "0"); } else { out += sprintf (out, "%d", weapon->Ammo1 != NULL ? weapon->Ammo1->Amount : 0); if (weapon->Ammo2 != NULL) { out += sprintf (out, "/%d", weapon->Ammo2->Amount); } } } } else if (len == 4) { if (strnicmp (a, "ammo", 4) == 0) { if (weapon == NULL || weapon->Ammo1 == NULL) { out += sprintf (out, "no ammo"); } else { out += sprintf (out, "%s", weapon->Ammo1->GetClass()->Name+1); if (weapon->Ammo2 != NULL) { out += sprintf (out, "/%s", weapon->Ammo2->GetClass()->Name+1); } } } } else if (len == 0) { *out++ = '$'; *out = 0; if (*b == '$') { b++; } } else { *out++ = '$'; strncpy (out, a, len); out += len; } a = b; } // Return false if no substitution was performed if (a == in) { return false; } strcpy (out, a); return true; }
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) { 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_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 } } } }
void AsbrPickableItem_Grenade::GivePickupTo(class AsbrCharacter* Pawn) { AWeapon* Weapon = (Pawn ? Pawn->FindWeapon(WeaponType) : NULL); if (Weapon) Weapon->GiveGrenade(Count); }
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 {