/** * Checks if the player has enough ammo to fire their readied weapon. * If not, a weapon change is instigated. * * @return @c true, if there is enough ammo to fire. */ boolean P_CheckAmmo(player_t* plr) { int fireMode; boolean good; ammotype_t i; weaponinfo_t* wInfo; wInfo = &weaponInfo[plr->readyWeapon][plr->class_]; #if __JDOOM__ || __JDOOM64__ || __JHEXEN__ fireMode = 0; #endif #if __JHERETIC__ // If deathmatch always use firemode two ammo requirements. if(plr->powers[PT_WEAPONLEVEL2] && !deathmatch) fireMode = 1; else fireMode = 0; #endif #if __JHEXEN__ //// @todo Kludge: Work around the multiple firing modes problems. //// We need to split the weapon firing routines and implement them as //// new fire modes. if(plr->class_ == PCLASS_FIGHTER && plr->readyWeapon != WT_FOURTH) return true; // < KLUDGE #endif // Check we have enough of ALL ammo types used by this weapon. good = true; for(i = 0; i < NUM_AMMO_TYPES && good; ++i) { if(!wInfo->mode[fireMode].ammoType[i]) continue; // Weapon does not take this type of ammo. // Minimal amount for one shot varies. if(plr->ammo[i].owned < wInfo->mode[fireMode].perShot[i]) { // Insufficent ammo to fire this weapon. good = false; } } if(good) return true; // Out of ammo, pick a weapon to change to. P_MaybeChangeWeapon(plr, WT_NOCHANGE, AT_NOAMMO, false); // Now set appropriate weapon overlay. if(plr->pendingWeapon != WT_NOCHANGE) P_SetPsprite(plr, ps_weapon, wInfo->mode[fireMode].states[WSN_DOWN]); return false; }
static dd_bool giveOneWeapon(player_t *plr, weapontype_t weaponType, dd_bool dropped) { int numClips = numAmmoClipsToGiveWithWeapon(dropped); dd_bool gaveAmmo = false, gaveWeapon = false; weaponinfo_t const *wpnInfo; ammotype_t i; DENG_ASSERT(plr != 0); DENG_ASSERT(weaponType >= WT_FIRST && weaponType < NUM_WEAPON_TYPES); wpnInfo = &weaponInfo[weaponType][plr->class_]; // Do not give weapons unavailable for the current mode. if(!(wpnInfo->mode[0].gameModeBits & gameModeBits)) return false; // Give some of each of the ammo types used by this weapon. for(i = 0; i < NUM_AMMO_TYPES; ++i) { // Is this ammo type usable?. if(!wpnInfo->mode[0].ammoType[i]) continue; if(P_GiveAmmo(plr, i, numClips)) { gaveAmmo = true; } } if(!plr->weapons[weaponType].owned) { gaveWeapon = true; plr->weapons[weaponType].owned = true; plr->update |= PSF_OWNED_WEAPONS; // Animate a pickup bonus flash? if(IS_NETGAME && G_Ruleset_Deathmatch() != 2 && !dropped) { plr->bonusCount += BONUSADD; } // Given the new weapon the player may want to change automatically. P_MaybeChangeWeapon(plr, weaponType, AT_NOAMMO, shouldForceWeaponChange(dropped)); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_WEAPON); } return (gaveWeapon || gaveAmmo); }
static dd_bool giveOneAmmo(player_t *plr, ammotype_t ammoType, int numClips) { int numRounds = 0; DENG_ASSERT(plr != 0); DENG_ASSERT((ammoType >= 0 && ammoType < NUM_AMMO_TYPES) || ammoType == AT_NOAMMO); // Giving the special 'unlimited ammo' type always succeeds. if(ammoType == AT_NOAMMO) return true; // Already fully stocked? if(plr->ammo[ammoType].owned >= plr->ammo[ammoType].max) return false; // Translate number of clips to individual rounds. if(numClips >= 1) { numRounds = numClips * clipAmmo[ammoType]; } else if(numClips == 0) { // Half of one clip. numRounds = clipAmmo[ammoType] / 2; } else { // Fully replenish. numRounds = plr->ammo[ammoType].max; } // Give double the number of rounds at easy/nightmare skill levels. if(G_Ruleset_Skill() == SM_BABY || G_Ruleset_Skill() == SM_NIGHTMARE) { numRounds *= 2; } // Given the new ammo the player may want to change weapon automatically. P_MaybeChangeWeapon(plr, WT_NOCHANGE, ammoType, false /*don't force*/); // Restock the player. plr->ammo[ammoType].owned = MIN_OF(plr->ammo[ammoType].max, plr->ammo[ammoType].owned + numRounds); plr->update |= PSF_AMMO; // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_AMMO); return true; }
/** * The weapon name may have a MF_DROPPED flag ored in. */ boolean P_GiveWeapon(player_t *player, weapontype_t weapon, boolean dropped) { ammotype_t i; boolean gaveammo = false; boolean gaveweapon; int numClips; if(IS_NETGAME && (deathmatch != 2) && !dropped) { // leave placed weapons forever on net games if(player->weaponOwned[weapon]) return false; player->bonusCount += BONUSADD; player->weaponOwned[weapon] = true; player->update |= PSF_OWNED_WEAPONS; // Give some of each of the ammo types used by this weapon. for(i=0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class].mode[0].ammoType[i]) continue; // Weapon does not take this type of ammo. if(deathmatch) numClips = 5; else numClips = 2; if(P_GiveAmmo(player, i, numClips)) gaveammo = true; // at least ONE type of ammo was given. } // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, deathmatch == 1); // Maybe unhide the HUD? if(player == &players[CONSOLEPLAYER]) ST_HUDUnHide(HUE_ON_PICKUP_WEAPON); S_ConsoleSound(SFX_WPNUP, NULL, player - players); return false; } else { // Give some of each of the ammo types used by this weapon. for(i=0; i < NUM_AMMO_TYPES; ++i)
/** * @param num Number of clip loads, not the individual count. * * @return @c false, if the ammo can't be picked up at all. */ boolean P_GiveAmmo(player_t* player, ammotype_t ammo, int num) { if(ammo == AT_NOAMMO) return false; if(ammo < 0 || ammo > NUM_AMMO_TYPES) Con_Error("P_GiveAmmo: bad type %i", ammo); if(player->ammo[ammo] == player->maxAmmo[ammo]) return false; if(num) num *= clipAmmo[ammo]; else num = clipAmmo[ammo] / 2; if(gameskill == SM_BABY || gameskill == SM_NIGHTMARE) { // give double ammo in trainer mode, // you'll need in nightmare num <<= 1; } // We are about to receive some more ammo. Does the player want to // change weapon automatically? P_MaybeChangeWeapon(player, WT_NOCHANGE, ammo, false); player->ammo[ammo] += num; player->update |= PSF_AMMO; if(player->ammo[ammo] > player->maxAmmo[ammo]) player->ammo[ammo] = player->maxAmmo[ammo]; // Maybe unhide the HUD? if(player == &players[CONSOLEPLAYER]) ST_HUDUnHide(HUE_ON_PICKUP_AMMO); return true; }
/** * @param player Player to be given ammo. * @param ammo Type of ammo to be given. * @param num Number of clip loads, not the individual count. * * @return @c false, if the ammo can't be picked up at all. */ dd_bool P_GiveAmmo(player_t *player, ammotype_t ammo, int num) { if(ammo == AT_NOAMMO) return false; if(ammo < 0 || ammo > NUM_AMMO_TYPES) Con_Error("P_GiveAmmo: bad type %i", ammo); if(!(player->ammo[ammo].owned < player->ammo[ammo].max)) return false; if(num) num *= clipAmmo[ammo]; else num = clipAmmo[ammo] / 2; if(G_Ruleset_Skill() == SM_BABY) { // Give double ammo in trainer mode. num <<= 1; } // We are about to receive some more ammo. Does the player want to // change weapon automatically? P_MaybeChangeWeapon(player, WT_NOCHANGE, ammo, false); if(player->ammo[ammo].owned + num > player->ammo[ammo].max) player->ammo[ammo].owned = player->ammo[ammo].max; else player->ammo[ammo].owned += num; player->update |= PSF_AMMO; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_AMMO); return true; }
/** * The weapon name may have a MF_DROPPED flag ored in. */ dd_bool P_GiveWeapon(player_t *player, weapontype_t weapon, dd_bool dropped) { ammotype_t i; dd_bool gaveAmmo = false; dd_bool gaveWeapon; int numClips; if(IS_NETGAME && (G_Ruleset_Deathmatch() != 2) && !dropped) { // leave placed weapons forever on net games if(player->weapons[weapon].owned) return false; player->bonusCount += BONUSADD; player->weapons[weapon].owned = true; player->update |= PSF_OWNED_WEAPONS; // Give some of each of the ammo types used by this weapon. for(i = 0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class_].mode[0].ammoType[i]) continue; // Weapon does not take this type of ammo. if(G_Ruleset_Deathmatch()) numClips = 5; else numClips = 2; if(P_GiveAmmo(player, i, numClips)) gaveAmmo = true; // At least ONE type of ammo was given. } // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, G_Ruleset_Deathmatch() == 1); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); S_ConsoleSound(SFX_WPNUP, NULL, player - players); return false; } else { // Give some of each of the ammo types used by this weapon. for(i = 0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class_].mode[0].ammoType[i]) continue; // Weapon does not take this type of ammo. // Give one clip with a dropped weapon, two clips with a found // weapon. if(dropped) numClips = 1; else numClips = 2; if(P_GiveAmmo(player, i, numClips)) gaveAmmo = true; // At least ONE type of ammo was given. } if(player->weapons[weapon].owned) gaveWeapon = false; else { gaveWeapon = true; player->weapons[weapon].owned = true; player->update |= PSF_OWNED_WEAPONS; // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, false); } // Maybe unhide the HUD? if(gaveWeapon) ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); return (gaveWeapon || gaveAmmo); } }