// // A_Lower // Lowers current weapon, // and changes weapon at bottom. // void A_Lower(player_t* player, pspdef_t* psp) { psp->sy += LOWERSPEED; // Is already down. if(psp->sy < WEAPONBOTTOM ) return; // Player is dead. if(player->playerstate == PST_DEAD) { psp->sy = WEAPONBOTTOM; // don't bring weapon back up return; } // // [d64] stop plasma buzz // if(player->readyweapon == wp_plasma) { pls_buzzing = false; S_StopSound(NULL, sfx_electric); } // The old weapon has been lowered off the screen, // so change the weapon and start raising it if(!player->health) { // Player is dead, so keep the weapon off screen. P_SetPsprite(player, ps_weapon, S_000); return; } P_SetPsprite(player, ps_flash, S_000); //villsa player->readyweapon = player->pendingweapon; P_BringUpWeapon(player); }
void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index) { PClassActor *cls = weapon->GetClass(); while (cls != RUNTIME_CLASS(AWeapon)) { if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates) { // The flash state belongs to this class. // Now let's check if the actually wanted state does also if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates) { // we're ok so set the state P_SetPsprite (player, ps_flash, flashstate + index); player->psprites[ps_flash].processPending = true; return; } else { // oh, no! The state is beyond the end of the state table so use the original flash state. P_SetPsprite (player, ps_flash, flashstate); player->psprites[ps_flash].processPending = true; return; } } // try again with parent class cls = static_cast<PClassActor *>(cls->ParentClass); } // if we get here the state doesn't seem to belong to any class in the inheritance chain // This can happen with Dehacked if the flash states are remapped. // The only way to check this would be to go through all Dehacked modifiable actors, convert // their states into a single flat array and find the correct one. // Rather than that, just check to make sure it belongs to something. if (FState::StaticFindStateOwner(flashstate + index) == NULL) { // Invalid state. With no index offset, it should at least be valid. index = 0; } P_SetPsprite (player, ps_flash, flashstate + index); player->psprites[ps_flash].processPending = true; }
void P_DropWeapon (player_t *player) { if (player == NULL) { return; } // Since the weapon is dropping, stop blocking switching. player->WeaponState &= ~WF_DISABLESWITCH; if (player->ReadyWeapon != NULL) { P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetDownState()); } }
void A_CheckReload(player_t *player, pspdef_t *psp) { CHECK_WEAPON_CODEPOINTER("A_CheckReload", player); if (!P_CheckAmmo(player) && compatibility_level >= prboom_4_compatibility) { /* cph 2002/08/08 - In old Doom, P_CheckAmmo would start the weapon lowering * immediately. This was lost in Boom when the weapon switching logic was * rewritten. But we must tell Doom that we don't need to complete the * reload frames for the weapon here. G_BuildTiccmd will set ->pendingweapon * for us later on. */ P_SetPsprite(player,ps_weapon,weaponinfo[player->readyweapon].downstate); } }
void P_DropWeapon (player_t *player) { if (player == nullptr) { return; } // Since the weapon is dropping, stop blocking switching. player->WeaponState &= ~WF_DISABLESWITCH; if ((player->ReadyWeapon != nullptr) && (player->health > 0 || !(player->ReadyWeapon->WeaponFlags & WIF_NODEATHDESELECT))) { P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetDownState()); } }
// // A_FirePlasma // void A_FirePlasma (AActor *mo) { player_t *player = mo->player; DecreaseAmmo(player); P_SetPsprite (player, ps_flash, (statenum_t)(weaponinfo[player->readyweapon].flashstate+(P_Random (player->mo)&1))); if(serverside) P_SpawnPlayerMissile (player->mo, MT_PLASMA); }
OVERLAY static void P_FireWeapon(player_t *player) { statenum_t newstate; if (!P_CheckAmmo(player)) return; P_SetMobjState(player->mo, S_PLAY_ATK1); newstate = (statenum_t)weaponinfo[player->readyweapon].atkstate; P_SetPsprite(player, ps_weapon, newstate); P_NoiseAlert(player->mo, player->mo); lastshottic = gametic; // killough 3/22/98 }
void A_FAxeCheckAtk (AActor *actor) { player_t *player; if (NULL == (player = actor->player)) { return; } if (player->ReadyWeapon->Ammo1->Amount) { P_SetPsprite (player, ps_weapon, &AFWeapAxe::States[S_FAXEATK_G]); } }
DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) { player_t *player; if (NULL == (player = self->player)) { return; } if (player->ReadyWeapon->Ammo1->Amount) { P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("FireGlow")); } }
// // A_WeaponReady // The player can fire the weapon // or change to another weapon at this time. // Follows after getting weapon up, // or after previous attack/fire sequence. // void A_WeaponReady(AActor *mo) { statenum_t newstate; player_t *player = mo->player; struct pspdef_s *psp = &player->psprites[player->psprnum]; // get out of attack state if (player->mo->state == &states[S_PLAY_ATK1] || player->mo->state == &states[S_PLAY_ATK2] ) { P_SetMobjState (player->mo, S_PLAY); } if (player->readyweapon == wp_chainsaw && psp->state == &states[S_SAW]) { A_FireSound(player, "weapons/sawidle"); } // check for change // if player is dead, put the weapon away if (player->pendingweapon != wp_nochange || player->health <= 0) { // change weapon // (pending weapon should already be validated) newstate = weaponinfo[player->readyweapon].downstate; P_SetPsprite (player, ps_weapon, newstate); return; } // check for fire // the missile launcher and bfg do not auto fire // [AM] Allow warmup to disallow weapon firing. if (player->cmd.ucmd.buttons & BT_ATTACK && warmup.checkfireweapon()) { if ( !player->attackdown || (player->readyweapon != wp_missile && player->readyweapon != wp_bfg) ) { player->attackdown = true; P_FireWeapon (player); return; } } else player->attackdown = false; // bob the weapon based on movement speed P_BobWeapon(player); }
// // A_WeaponReady // The player can fire the weapon // or change to another weapon at this time. // Follows after getting weapon up, // or after previous attack/fire sequence. // void A_WeaponReady(player_t *player, pspdef_t *psp) { // get out of attack state if (player->mo->state == &states[S_PLAY_ATK1] || player->mo->state == &states[S_PLAY_ATK2]) P_SetMobjState(player->mo, S_PLAY); if (player->readyweapon == wp_chainsaw && psp->state == &states[S_SAW]) S_StartSound(player->mo, sfx_sawidl); // check for change // if player is dead, put the weapon away if (player->pendingweapon != wp_nochange || !player->health) { // change weapon (pending weapon should already be validated) P_SetPsprite(player, ps_weapon, (statenum_t)weaponinfo[player->readyweapon].downstate); return; } // check for fire // the missile launcher and bfg do not auto fire if (player->cmd.buttons & BT_ATTACK) { if (!player->attackdown || (player->readyweapon != wp_missile && player->readyweapon != wp_bfg)) { player->attackdown = true; P_FireWeapon(player); return; } } else player->attackdown = false; if (player->mo->momx || player->mo->momy || player->mo->momz) { // bob the weapon based on movement speed int angle = (128 * leveltime) & FINEMASK; int bob = player->bob; if (bob < FRACUNIT / 2) bob = 0; psp->sx = FixedMul(bob, finecosine[angle]); psp->sy = WEAPONTOP + FixedMul(bob, finesine[angle & FINEANGLES / 2 - 1]); } else { psp->sx = 0; psp->sy = WEAPONTOP; } }
/** * The player can fire the weapon or change to another weapon at this time. * Follows after getting weapon up, or after previous attack/fire sequence. */ void C_DECL A_WeaponReady(player_t* player, pspdef_t* psp) { weaponmodeinfo_t* wminfo; // Enable the pspr Y offset (might be disabled in A_Lower). DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); // Get out of attack state. if(player->plr->mo->state == &STATES[PCLASS_INFO(player->class_)->attackState] || player->plr->mo->state == &STATES[PCLASS_INFO(player->class_)->attackEndState]) { P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class_)->normalState); } if(player->readyWeapon != WT_NOCHANGE) { wminfo = WEAPON_INFO(player->readyWeapon, player->class_, 0); // A weaponready sound? if(psp->state == &STATES[wminfo->states[WSN_READY]] && wminfo->readySound) S_StartSound(wminfo->readySound, player->plr->mo); // Check for change. If player is dead, put the weapon away. if(player->pendingWeapon != WT_NOCHANGE || !player->health) { // (pending weapon should allready be validated) P_SetPsprite(player, ps_weapon, wminfo->states[WSN_DOWN]); return; } } // Check for autofire. if(player->brain.attack) { wminfo = WEAPON_INFO(player->readyWeapon, player->class_, 0); if(!player->attackDown || wminfo->autoFire) { player->attackDown = true; P_FireWeapon(player); return; } } else player->attackDown = false; // Bob the weapon based on movement speed. R_GetWeaponBob(player - players, &psp->pos[0], &psp->pos[1]); // Psprite state. player->plr->pSprites[0].state = DDPSP_BOBBING; }
void P_PostChickenWeapon(player_t *player, weapontype_t weapon) { if(weapon == wp_beak) { // Should never happen //weapon = wp_staff; return; } player->pendingweapon = wp_nochange; player->readyweapon = weapon; player->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON; player->psprites[ps_weapon].sy = WEAPONBOTTOM; P_SetPsprite(player, ps_weapon, wpnlev1info[weapon].upstate); NetSv_PSpriteChange(player - players, wpnlev1info[weapon].upstate); }
// // A_Raise // void A_Raise(player_t *player, pspdef_t *psp) { psp->sy -= RAISESPEED; if (psp->sy > WEAPONTOP) return; psp->sy = WEAPONTOP; startingnewgame = false; // The weapon has been raised all the way, // so change to the ready state. P_SetPsprite(player, ps_weapon, (statenum_t)weaponinfo[player->readyweapon].readystate); }
// // A_FirePistol // void A_FirePistol(player_t* player, pspdef_t* psp) { S_StartSound(player->mo, sfx_pistol); P_SetMobjState(player->mo, S_007); player->ammo[weaponinfo[player->readyweapon].ammo]--; P_SetPsprite(player, ps_flash, weaponinfo[player->readyweapon].flashstate); P_BulletSlope(player->mo); P_GunShot(player->mo, !player->refire); }
DEFINE_ACTION_FUNCTION(AActor, A_BeakRaise) { PARAM_ACTION_PROLOGUE; player_t *player; if (NULL == (player = self->player)) { return 0; } player->psprites[ps_weapon].sy = WEAPONTOP; P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetReadyState()); return 0; }
DEFINE_ACTION_FUNCTION(AInventory, A_Lower) { PARAM_ACTION_PROLOGUE; player_t *player = self->player; pspdef_t *psp; if (NULL == player) { return 0; } psp = &player->psprites[ps_weapon]; if (player->morphTics || player->cheats & CF_INSTANTWEAPSWITCH) { psp->sy = WEAPONBOTTOM; } else { psp->sy += LOWERSPEED; } if (psp->sy < WEAPONBOTTOM) { // Not lowered all the way yet return 0; } if (player->playerstate == PST_DEAD) { // Player is dead, so don't bring up a pending weapon psp->sy = WEAPONBOTTOM; // Player is dead, so keep the weapon off screen P_SetPsprite (player, ps_weapon, NULL); return 0; } // [RH] Clear the flash state. Only needed for Strife. P_SetPsprite (player, ps_flash, NULL); P_BringUpWeapon (player); return 0; }
// // A_Raise // void A_Raise(player_t* player, pspdef_t* psp) { statenum_t newstate; psp->sy -= RAISESPEED; if (psp->sy > WEAPONTOP ) return; psp->sy = WEAPONTOP; // The weapon has been raised all the way, // so change to the ready state. newstate = weaponinfo[player->readyweapon].readystate; P_SetPsprite(player, ps_weapon, newstate); }
void P_FireWeapon(player_t *player) { statenum_t newstate; if(!P_CheckAmmo(player)) return; // Psprite state. player->plr->pSprites[0].state = DDPSP_FIRE; P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class_)->attackState); newstate = weaponInfo[player->readyWeapon][player->class_].mode[0].states[WSN_ATTACK]; P_SetPsprite(player, ps_weapon, newstate); P_NoiseAlert(player->plr->mo, player->plr->mo); }
// // A_WeaponCtrSwitch // // This powerful codepointer can branch to one of N states // depending on the value of the indicated counter, and it // remains totally safe at all times. If the entire indicated // frame set is not valid, no actions will be taken. // // args[0] : counter # to use // args[1] : DeHackEd number of first frame in consecutive set // args[2] : number of frames in consecutive set // args[3] : psprite to affect (weapon or flash) // void A_WeaponCtrSwitch(Mobj *mo) { int cnum, startstate, numstates, psprnum; int *counter; player_t *player; pspdef_t *pspr; if(!(player = mo->player)) return; pspr = &(player->psprites[player->curpsprite]); cnum = E_ArgAsInt(pspr->state->args, 0, 0); startstate = E_ArgAsStateNumNI(pspr->state->args, 1, NULL); numstates = E_ArgAsInt(pspr->state->args, 2, 0) - 1; psprnum = E_ArgAsKwd(pspr->state->args, 3, &psprkwds, 0); // validate psprite number if(psprnum < 0 || psprnum >= NUMPSPRITES) return; // get counter switch(cnum) { case 0: case 1: case 2: counter = &(player->weaponctrs[player->readyweapon][cnum]); break; default: return; } // verify startstate if(startstate < 0) return; // verify last state is < NUMSTATES if(startstate + numstates >= NUMSTATES) return; // verify counter is in range if(*counter < 0 || *counter > numstates) return; // jump! P_SetPsprite(player, psprnum, startstate + *counter); }
// // P_FireWeapon. // void P_FireWeapon(player_t *player) { statenum_t newstate; if (!P_CheckAmmo(player) || (automapactive && !followplayer)) return; P_SetMobjState(player->mo, S_PLAY_ATK1); newstate = (statenum_t)weaponinfo[player->readyweapon].atkstate; P_SetPsprite(player, ps_weapon, newstate); if (player->readyweapon == wp_fist && !linetarget) return; P_NoiseAlert(player->mo, player->mo); }
OVERLAY void P_MovePsprites(player_t *player) { pspdef_t *psp = player->psprites; int i; // a null state means not active // drop tic count and possibly change state // a -1 tic count never changes for (i=0; i<NUMPSPRITES; i++, psp++) if (psp->state && psp->tics != -1 && !--psp->tics) P_SetPsprite(player, i, psp->state->nextstate); player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; }
// // 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; }
OVERLAY static void P_BringUpWeapon(player_t *player) { statenum_t newstate; if (player->pendingweapon == wp_nochange) player->pendingweapon = player->readyweapon; if (player->pendingweapon == wp_chainsaw) S_StartSound (player->mo, sfx_sawup); newstate = (statenum_t)weaponinfo[player->pendingweapon].upstate; player->pendingweapon = wp_nochange; player->psprites[ps_weapon].sy = WEAPONBOTTOM; P_SetPsprite(player, ps_weapon, newstate); }
DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) { player_t *player; if (NULL == (player = self->player)) { return; } if (player->ReadyWeapon->Ammo1->Amount <= 0) { P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("Select")); } else { CALL_ACTION(A_Raise, self); } }
DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) { player_t *player; if (NULL == (player = self->player)) { return; } if (player->ReadyWeapon->Ammo1->Amount <= 0) { P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("Ready")); } else { DoReadyWeapon(self); } }
void A_FAxeCheckUpG (AActor *actor) { player_t *player; if (NULL == (player = actor->player)) { return; } if (player->ReadyWeapon->Ammo1->Amount <= 0) { P_SetPsprite (player, ps_weapon, &AFWeapAxe::States[S_FAXEUP]); } else { A_Raise (actor); } }
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; }
void A_WeaponReady(player_t* player, pspdef_t* psp) { statenum_t newstate; int angle; // get out of attack state if (player->mo->state == &states[S_006] || player->mo->state == &states[S_007] ) { P_SetMobjState (player->mo, S_001); } // check for change // if player is dead, put the weapon away if (player->pendingweapon != wp_nochange || !player->health) { // change weapon // (pending weapon should allready be validated) newstate = weaponinfo[player->readyweapon].downstate; P_SetPsprite (player, ps_weapon, newstate); return; } // check for fire // the missile launcher and bfg do not auto fire if (player->cmd.buttons & BT_ATTACK) { if ( !player->attackdown || (player->readyweapon != wp_missile && player->readyweapon != wp_bfg) ) { player->attackdown = true; P_FireWeapon (player); return; } } else player->attackdown = false; // bob the weapon based on movement speed angle = (128*leveltime)&FINEMASK; psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); angle &= FINEANGLES/2-1; psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); }
// // P_BringUpWeapon // Starts bringing the pending weapon up // from the bottom of the screen. // Uses player // void P_BringUpWeapon (player_t *player) { statenum_t newstate; if (player->pendingweapon == wp_nochange) player->pendingweapon = player->readyweapon; if (player->pendingweapon == wp_chainsaw) A_FireSound(player, "weapons/sawup"); newstate = weaponinfo[player->pendingweapon].upstate; player->pendingweapon = wp_nochange; player->psprites[ps_weapon].sy = WEAPONBOTTOM; weapon_ypos[player->id] = WEAPONBOTTOM; P_SetPsprite (player, ps_weapon, newstate); }