dd_bool P_GivePower(player_t* player, int power) { player->update |= PSF_POWERS; switch(power) { case PT_INVULNERABILITY: player->powers[power] = INVULNTICS; break; case PT_INVISIBILITY: player->powers[power] = INVISTICS; player->plr->mo->flags |= MF_SHADOW;; break; case PT_FLIGHT: player->powers[power] = 1; player->plr->mo->flags2 |= MF2_FLY; player->plr->mo->flags |= MF_NOGRAVITY; if(player->plr->mo->origin[VZ] <= player->plr->mo->floorZ) { player->flyHeight = 10; // Thrust the player in the air a bit. player->plr->mo->flags |= DDPF_FIXMOM; } break; case PT_INFRARED: player->powers[power] = INFRATICS; break; case PT_IRONFEET: player->powers[power] = IRONTICS; break; case PT_STRENGTH: P_GiveBody(player, maxHealth); player->powers[power] = 1; break; default: if(player->powers[power]) return false; // Already got it. player->powers[power] = 1; break; } if(power == PT_ALLMAP) ST_RevealAutomap(player - players, true); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_POWER); return true; }
void P_GiveKey(player_t* player, keytype_t card) { if(player->keys[card]) return; player->bonusCount = BONUSADD; player->keys[card] = 1; player->update |= PSF_KEYS; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_KEY); }
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); }
dd_bool P_GiveArmor(player_t* plr, int type, int points) { if(plr->armorPoints >= points) return false; // Don't pick up. P_PlayerSetArmorType(plr, type); P_PlayerGiveArmorBonus(plr, points - plr->armorPoints); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); return true; }
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; }
static dd_bool giveOneKey(player_t *plr, keytype_t keyType) { DENG_ASSERT(plr != 0); DENG_ASSERT(keyType >= KT_FIRST && keyType < NUM_KEY_TYPES); // Already owned? if(plr->keys[keyType]) return false; plr->keys[keyType] = 1; plr->bonusCount = BONUSADD; plr->update |= PSF_KEYS; // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_KEY); return true; }
dd_bool P_GiveHealth(player_t *player, int amount) { if(player->health >= maxHealth) return false; player->health += amount; if(player->health > maxHealth) player->health = maxHealth; player->plr->mo->health = player->health; player->update |= PSF_HEALTH; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_HEALTH); 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; }
/** * @param plr Player being given item. * @param item Type of item being given. * @param dropped @c true = the item was dropped by some entity. * * @return @c true iff the item should be destroyed. */ static dd_bool pickupItem(player_t *plr, itemtype_t item, dd_bool dropped) { if(!plr) return false; switch(item) { case IT_ARMOR_GREEN: if(!P_GiveArmor(plr, armorClass[0], armorPoints[MINMAX_OF(0, armorClass[0] - 1, 1)])) return false; P_SetMessage(plr, 0, GOTARMOR); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ARMOR_BLUE: if(!P_GiveArmor(plr, armorClass[1], armorPoints[MINMAX_OF(0, armorClass[1] - 1, 1)])) return false; P_SetMessage(plr, 0, GOTMEGA); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ARMOR_BONUS: if(!plr->armorType) P_PlayerSetArmorType(plr, armorClass[0]); if(plr->armorPoints < armorPoints[1]) P_PlayerGiveArmorBonus(plr, 1); P_SetMessage(plr, 0, GOTARMBONUS); if(!mapSetup) { S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); } break; case IT_HEALTH_PACK: if(!P_GiveHealth(plr, 10)) return false; P_SetMessage(plr, 0, GOTSTIM); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_HEALTH_KIT: { int oldHealth = plr->health; /** * DOOM bug: * The following test was originaly placed AFTER the call to * P_GiveHealth thereby making the first outcome impossible as * the medikit gives 25 points of health. This resulted that * the GOTMEDINEED "Picked up a medikit that you REALLY need" * was never used. */ if(!P_GiveHealth(plr, 25)) return false; P_SetMessage(plr, 0, GET_TXT((oldHealth < 25)? TXT_GOTMEDINEED : TXT_GOTMEDIKIT)); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; } case IT_HEALTH_BONUS: plr->health++; // Can go over 100%. if(plr->health > healthLimit) plr->health = healthLimit; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_SetMessage(plr, 0, GOTHTHBONUS); if(!mapSetup) { S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); } break; case IT_HEALTH_SOULSPHERE: plr->health += soulSphereHealth; if(plr->health > soulSphereLimit) plr->health = soulSphereLimit; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_SetMessage(plr, 0, GOTSUPER); if(!mapSetup) { S_ConsoleSound(SFX_GETPOW, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); } break; case IT_KEY_BLUE: if(!plr->keys[KT_BLUECARD]) { P_GiveKey(plr, KT_BLUECARD); P_SetMessage(plr, 0, GOTBLUECARD); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } if(IS_NETGAME) return false; break; case IT_KEY_YELLOW: if(!plr->keys[KT_YELLOWCARD]) { P_GiveKey(plr, KT_YELLOWCARD); P_SetMessage(plr, 0, GOTYELWCARD); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } if(IS_NETGAME) return false; break; case IT_KEY_RED: if(!plr->keys[KT_REDCARD]) { P_GiveKey(plr, KT_REDCARD); P_SetMessage(plr, 0, GOTREDCARD); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } if(IS_NETGAME) return false; break; case IT_KEY_BLUESKULL: if(!plr->keys[KT_BLUESKULL]) { P_GiveKey(plr, KT_BLUESKULL); P_SetMessage(plr, 0, GOTBLUESKUL); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } if(IS_NETGAME) return false; break; case IT_KEY_YELLOWSKULL: if(!plr->keys[KT_YELLOWSKULL]) { P_GiveKey(plr, KT_YELLOWSKULL); P_SetMessage(plr, 0, GOTYELWSKUL); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } if(IS_NETGAME) return false; break; case IT_KEY_REDSKULL: if(!plr->keys[KT_REDSKULL]) { P_GiveKey(plr, KT_REDSKULL); P_SetMessage(plr, 0, GOTREDSKULL); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } if(IS_NETGAME) return false; break; case IT_MEGASPHERE: if(!(gameModeBits & GM_ANY_DOOM2)) return false; plr->health = megaSphereHealth; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_GiveArmor(plr, armorClass[1], armorPoints[MINMAX_OF(0, armorClass[1] - 1, 1)]); P_SetMessage(plr, 0, GOTMSPHERE); if(!mapSetup) { S_ConsoleSound(SFX_GETPOW, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); } break; case IT_INVUL: if(!P_GivePower(plr, PT_INVULNERABILITY)) return false; P_SetMessage(plr, 0, GOTINVUL); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_BERSERK: if(!P_GivePower(plr, PT_STRENGTH)) return false; P_SetMessage(plr, 0, GOTBERSERK); if(plr->readyWeapon != WT_FIRST && cfg.berserkAutoSwitch) { plr->pendingWeapon = WT_FIRST; plr->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON; } if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_INVIS: if(!P_GivePower(plr, PT_INVISIBILITY)) return false; P_SetMessage(plr, 0, GOTINVIS); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_SUIT: if(!P_GivePower(plr, PT_IRONFEET)) return false; P_SetMessage(plr, 0, GOTSUIT); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_ALLMAP: if(!P_GivePower(plr, PT_ALLMAP)) return false; P_SetMessage(plr, 0, GOTMAP); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_VISOR: if(!P_GivePower(plr, PT_INFRARED)) return false; P_SetMessage(plr, 0, GOTVISOR); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_BACKPACK: P_GiveBackpack(plr); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CLIP: if(!P_GiveAmmo(plr, AT_CLIP, dropped? 0 /*half a clip*/ : 1)) return false; P_SetMessage(plr, 0, GOTCLIP); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CLIP_BOX: if(!P_GiveAmmo(plr, AT_CLIP, 5)) return false; P_SetMessage(plr, 0, GOTCLIPBOX); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_ROCKET: if(!P_GiveAmmo(plr, AT_MISSILE, 1)) return false; P_SetMessage(plr, 0, GOTROCKET); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_ROCKET_BOX: if(!P_GiveAmmo(plr, AT_MISSILE, 5)) return false; P_SetMessage(plr, 0, GOTROCKBOX); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CELL: if(!P_GiveAmmo(plr, AT_CELL, 1)) return false; P_SetMessage(plr, 0, GOTCELL); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CELL_BOX: if(!P_GiveAmmo(plr, AT_CELL, 5)) return false; P_SetMessage(plr, 0, GOTCELLBOX); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_SHELL: if(!P_GiveAmmo(plr, AT_SHELL, 1)) return false; P_SetMessage(plr, 0, GOTSHELLS); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_SHELL_BOX: if(!P_GiveAmmo(plr, AT_SHELL, 5)) return false; P_SetMessage(plr, 0, GOTSHELLBOX); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_WEAPON_BFG: return pickupWeapon(plr, WT_SEVENTH, dropped, GOTBFG9000); case IT_WEAPON_CHAINGUN: return pickupWeapon(plr, WT_FOURTH, dropped, GOTCHAINGUN); case IT_WEAPON_CHAINSAW: return pickupWeapon(plr, WT_EIGHTH, dropped, GOTCHAINSAW); case IT_WEAPON_RLAUNCHER: return pickupWeapon(plr, WT_FIFTH, dropped, GOTLAUNCHER); case IT_WEAPON_PLASMARIFLE: return pickupWeapon(plr, WT_SIXTH, dropped, GOTPLASMA); case IT_WEAPON_SHOTGUN: return pickupWeapon(plr, WT_THIRD, dropped, GOTSHOTGUN); case IT_WEAPON_SSHOTGUN: return pickupWeapon(plr, WT_NINETH, dropped, GOTSHOTGUN2); default: Con_Error("pickupItem: Unknown item %i.", (int) item); } return true; }
dd_bool P_GivePower(player_t *player, powertype_t powerType) { DENG_ASSERT(player != 0); DENG_ASSERT(powerType >= PT_FIRST && powerType < NUM_POWER_TYPES); // Powers cannot be given to dead players. if(player->health <= 0) return false; player->update |= PSF_POWERS; switch(powerType) { case PT_INVULNERABILITY: player->powers[powerType] = INVULNTICS; break; case PT_INVISIBILITY: player->powers[powerType] = INVISTICS; player->plr->mo->flags |= MF_SHADOW; break; case PT_FLIGHT: player->powers[powerType] = 1; player->plr->mo->flags2 |= MF2_FLY; player->plr->mo->flags |= MF_NOGRAVITY; if(player->plr->mo->origin[VZ] <= player->plr->mo->floorZ) { player->flyHeight = 10; // Thrust the player in the air a bit. player->plr->mo->flags |= DDPF_FIXMOM; } break; case PT_INFRARED: player->powers[powerType] = INFRATICS; break; case PT_IRONFEET: player->powers[powerType] = IRONTICS; break; case PT_STRENGTH: P_GiveHealth(player, maxHealth); player->powers[powerType] = 1; break; default: if(player->powers[powerType]) return false; // Already got it. player->powers[powerType] = 1; break; } if(powerType == PT_ALLMAP) ST_RevealAutomap(player - players, true); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_POWER); 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); } }