void P_PlayerOnSpecialFlat (player_t *player, int floorType) { if (Terrains[floorType].DamageAmount && !(level.time & Terrains[floorType].DamageTimeMask)) { AInventory *ironfeet = NULL; if (Terrains[floorType].AllowProtection) { for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory) { if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet))) break; } } int damage = 0; if (ironfeet == NULL) { damage = P_DamageMobj (player->mo, NULL, NULL, Terrains[floorType].DamageAmount, Terrains[floorType].DamageMOD); } if (damage > 0 && Terrains[floorType].Splash != -1) { S_Sound (player->mo, CHAN_AUTO, Splashes[Terrains[floorType].Splash].NormalSplashSound, 1, ATTN_IDLE); } } }
static void DrawWeapons(player_t *CPlayer, int x, int y) { int k,j; AInventory *inv; // First draw all weapons in the inventory that are not assigned to a weapon slot for(inv = CPlayer->mo->Inventory; inv; inv = inv->Inventory) { if (inv->IsKindOf(RUNTIME_CLASS(AWeapon)) && !CPlayer->weapons.LocateWeapon(static_cast<AWeapon*>(inv)->GetClass(), NULL, NULL)) { DrawOneWeapon(CPlayer, x, y, static_cast<AWeapon*>(inv)); } } // And now everything in the weapon slots back to front for (k = NUM_WEAPON_SLOTS - 1; k >= 0; k--) for(j = CPlayer->weapons.Slots[k].Size() - 1; j >= 0; j--) { PClassActor *weap = CPlayer->weapons.Slots[k].GetWeapon(j); if (weap) { inv=CPlayer->mo->FindInventory(weap); if (inv) { DrawOneWeapon(CPlayer, x, y, static_cast<AWeapon*>(inv)); } } } }
void FGLRenderer::SetFixedColormap (player_t *player) { gl_fixedcolormap=CM_DEFAULT; // check for special colormaps player_t * cplayer = player->camera->player; if (cplayer) { if (cplayer->extralight == INT_MIN) { gl_fixedcolormap=CM_FIRSTSPECIALCOLORMAP + INVERSECOLORMAP; extralight=0; } else if (cplayer->fixedcolormap != NOFIXEDCOLORMAP) { gl_fixedcolormap = CM_FIRSTSPECIALCOLORMAP + cplayer->fixedcolormap; } else if (cplayer->fixedlightlevel != -1) { for(AInventory * in = cplayer->mo->Inventory; in; in = in->Inventory) { PalEntry color = in->GetBlend (); // Need special handling for light amplifiers if (in->IsKindOf(RUNTIME_CLASS(APowerTorch))) { gl_fixedcolormap = cplayer->fixedlightlevel + CM_TORCH; } else if (in->IsKindOf(RUNTIME_CLASS(APowerLightAmp))) { gl_fixedcolormap = CM_LITE; } } } } gl_RenderState.SetFixedColormap(gl_fixedcolormap); }
void P_AutoUseStrifeHealth (player_t *player) { TArray<AInventory *> Items; for(AInventory *inv = player->mo->Inventory; inv != NULL; inv = inv->Inventory) { if (inv->Amount > 0 && inv->IsKindOf(RUNTIME_CLASS(AHealthPickup))) { int mode = static_cast<AHealthPickup*>(inv)->autousemode; if (mode == 3) Items.Push(inv); } } if (!sv_disableautohealth) { while (Items.Size() > 0) { int maxhealth = 0; int index = -1; // Find the largest item in the list for(unsigned i = 0; i < Items.Size(); i++) { if (Items[i]->health > maxhealth) { index = i; maxhealth = Items[i]->Amount; } } while (player->health < 50) { if (!player->mo->UseInventory (Items[index])) break; } if (player->health >= 50) return; // Using all of this item was not enough so delete it and restart with the next best one Items.Delete(index); } } }
bool check(AActor * owner) { // An empty key list means that any key will do if (!keylist.Size()) { for (AInventory * item = owner->Inventory; item != NULL; item = item->Inventory) { if (item->IsKindOf (RUNTIME_CLASS(AKey))) { return true; } } return false; } else for(unsigned int i=0;i<keylist.Size();i++) { if (!keylist[i]->check(owner)) return false; } return true; }
void ShowPop (int popnum) { DBaseStatusBar::ShowPop(popnum); if (popnum == CurrentPop) { if (popnum == POP_Keys) { AInventory *item; int i; KeyPopPos += 10; KeyPopScroll = 280; for (item = CPlayer->mo->Inventory, i = 0; item != NULL; item = item->Inventory) { if (item->IsKindOf (RUNTIME_CLASS(AKey))) { if (i == KeyPopPos) { return; } i++; } } } PendingPop = POP_None; // Do not scroll keys horizontally when dropping the popscreen KeyPopScroll = 0; KeyPopPos -= 10; } else { KeyPopPos = 0; PendingPop = popnum; } }
void P_AutoUseHealth(player_t *player, int saveHealth) { TArray<AInventory *> NormalHealthItems; TArray<AInventory *> LargeHealthItems; for(AInventory *inv = player->mo->Inventory; inv != NULL; inv = inv->Inventory) { if (inv->Amount > 0 && inv->IsKindOf(RUNTIME_CLASS(AHealthPickup))) { int mode = static_cast<AHealthPickup*>(inv)->autousemode; if (mode == 1) NormalHealthItems.Push(inv); else if (mode == 2) LargeHealthItems.Push(inv); } } int normalhealth = CountHealth(NormalHealthItems); int largehealth = CountHealth(LargeHealthItems); bool skilluse = !!G_SkillProperty(SKILLP_AutoUseHealth); if (skilluse && normalhealth >= saveHealth) { // Use quartz flasks player->health += UseHealthItems(NormalHealthItems, saveHealth); } else if (largehealth >= saveHealth) { // Use mystic urns player->health += UseHealthItems(LargeHealthItems, saveHealth); } else if (skilluse && normalhealth + largehealth >= saveHealth) { // Use mystic urns and quartz flasks player->health += UseHealthItems(NormalHealthItems, saveHealth); if (saveHealth > 0) player->health += UseHealthItems(LargeHealthItems, saveHealth); } player->mo->health = player->health; }
// // P_PlayerInSpecialSector // Called every tic frame // that the player origin is in a special sector // void P_PlayerInSpecialSector (player_t *player, sector_t * sector) { if (sector == NULL) { // Falling, not all the way down yet? sector = player->mo->Sector; if (!player->mo->isAtZ(sector->LowestFloorAt(player->mo)) && !player->mo->waterlevel) { return; } } // Has hit ground. AInventory *ironfeet; // [RH] Apply any customizable damage if (sector->damageamount > 0) { // Allow subclasses. Better would be to implement it as armor and let that reduce // the damage as part of the normal damage procedure. Unfortunately, I don't have // different damage types yet, so that's not happening for now. for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory) { if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet))) break; } if (sector->Flags & SECF_ENDGODMODE) player->cheats &= ~CF_GODMODE; if ((ironfeet == NULL || pr_playerinspecialsector() < sector->leakydamage)) { if (sector->Flags & SECF_HAZARD) { player->hazardcount += sector->damageamount; player->hazardtype = sector->damagetype; player->hazardinterval = sector->damageinterval; } else if (level.time % sector->damageinterval == 0) { if (!(player->cheats & (CF_GODMODE|CF_GODMODE2))) P_DamageMobj(player->mo, NULL, NULL, sector->damageamount, sector->damagetype); if ((sector->Flags & SECF_ENDLEVEL) && player->health <= 10 && (!deathmatch || !(dmflags & DF_NO_EXIT))) { G_ExitLevel(0, false); } if (sector->Flags & SECF_DMGTERRAINFX) { P_HitWater(player->mo, player->mo->Sector, player->mo->Pos(), false, true, true); } } } } else if (sector->damageamount < 0) { if (level.time % sector->damageinterval == 0) { P_GiveBody(player->mo, -sector->damageamount, 100); } } if (sector->isSecret()) { sector->ClearSecret(); P_GiveSecret(player->mo, true, true, int(sector - sectors)); } }
static int DrawAmmo(player_t *CPlayer, int x, int y) { int i,j,k; char buf[256]; AInventory *inv; AWeapon *wi=CPlayer->ReadyWeapon; orderedammos.Clear(); if (0 == hud_showammo) { // Show ammo for current weapon if any if (wi) AddAmmoToList(wi); } else { // Order ammo by use of weapons in the weapon slots for (k = 0; k < NUM_WEAPON_SLOTS; k++) for(j = 0; j < CPlayer->weapons.Slots[k].Size(); j++) { PClassActor *weap = CPlayer->weapons.Slots[k].GetWeapon(j); if (weap) { // Show ammo for available weapons if hud_showammo CVAR is 1 // or show ammo for all weapons if hud_showammo is greater than 1 if (hud_showammo > 1 || CPlayer->mo->FindInventory(weap)) { AddAmmoToList((AWeapon*)GetDefaultByType(weap)); } } } // Now check for the remaining weapons that are in the inventory but not in the weapon slots for(inv=CPlayer->mo->Inventory;inv;inv=inv->Inventory) { if (inv->IsKindOf(RUNTIME_CLASS(AWeapon))) { AddAmmoToList((AWeapon*)inv); } } } // ok, we got all ammo types. Now draw the list back to front (bottom to top) int def_width = ConFont->StringWidth("000/000"); x-=def_width; int yadd = ConFont->GetHeight(); for(i=orderedammos.Size()-1;i>=0;i--) { PClassAmmo * type = orderedammos[i]; AAmmo * ammoitem = (AAmmo*)CPlayer->mo->FindInventory(type); AAmmo * inv = ammoitem? ammoitem : (AAmmo*)GetDefaultByType(orderedammos[i]); FTextureID AltIcon = GetHUDIcon(type); FTextureID icon = !AltIcon.isNull()? AltIcon : inv->Icon; if (!icon.isValid()) continue; int trans= (wi && (type==wi->AmmoType1 || type==wi->AmmoType2)) ? 0xc000:0x6000; int maxammo = inv->MaxAmount; int ammo = ammoitem? ammoitem->Amount : 0; mysnprintf(buf, countof(buf), "%3d/%3d", ammo, maxammo); int tex_width= clamp<int>(ConFont->StringWidth(buf)-def_width, 0, 1000); int fontcolor=( !maxammo ? CR_GRAY : ammo < ( (maxammo * hud_ammo_red) / 100) ? CR_RED : ammo < ( (maxammo * hud_ammo_yellow) / 100) ? CR_GOLD : CR_GREEN ); DrawHudText(ConFont, fontcolor, buf, x-tex_width, y+yadd, trans); DrawImageToBox(TexMan[icon], x-20, y, 16, 8, trans); y-=10; } return y; }
bool AWeaponPiece::TryPickup (AActor *&toucher) { AInventory * inv; AWeaponHolder * hold=NULL; bool shouldStay = PrivateShouldStay (); int gaveAmmo; AWeapon * Defaults=(AWeapon*)GetDefaultByType(WeaponClass); FullWeapon=NULL; for(inv=toucher->Inventory;inv;inv=inv->Inventory) { if (inv->IsKindOf(RUNTIME_CLASS(AWeaponHolder))) { hold=static_cast<AWeaponHolder*>(inv); if (hold->PieceWeapon==WeaponClass) break; hold=NULL; } } if (!hold) { hold=static_cast<AWeaponHolder*>(Spawn(RUNTIME_CLASS(AWeaponHolder), 0, 0, 0, NO_REPLACE)); hold->BecomeItem(); hold->AttachToOwner(toucher); hold->PieceMask=0; hold->PieceWeapon=WeaponClass; } if (shouldStay) { // Cooperative net-game if (hold->PieceMask & PieceValue) { // Already has the piece return false; } toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1); toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2); } else { // Deathmatch or singleplayer game gaveAmmo = toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1) + toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2); if (hold->PieceMask & PieceValue) { // Already has the piece, check if mana needed if (!gaveAmmo) return false; GoAwayAndDie(); return true; } } hold->PieceMask |= PieceValue; // Check if weapon assembled if (hold->PieceMask== (1<<Defaults->health)-1) { if (!toucher->FindInventory (WeaponClass)) { FullWeapon= static_cast<AWeapon*>(Spawn(WeaponClass, 0, 0, 0, NO_REPLACE)); // [BB] The collection of weapon pieces is handled on the server, so we // need to tell the client that the weapon is completed. if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( toucher ) && ( toucher->player )) SERVERCOMMANDS_GiveInventory( ULONG( toucher->player - players ), FullWeapon ); // The weapon itself should not give more ammo to the player! FullWeapon->AmmoGive1=0; FullWeapon->AmmoGive2=0; FullWeapon->AttachToOwner(toucher); FullWeapon->AmmoGive1=Defaults->AmmoGive1; FullWeapon->AmmoGive2=Defaults->AmmoGive2; } } // [Dusk] Update the ammo counts to the client if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( toucher ) && ( toucher->player )) SERVERCOMMANDS_SyncPlayerAmmoAmount( ULONG( toucher->player - players )); GoAwayAndDie(); return true; }
void DrawPopScreen (int bottom) { char buff[64]; const char *label; int i; AInventory *item; int xscale, yscale, left, top; int bars = (CurrentPop == POP_Status) ? imgINVPOP : imgINVPOP2; int back = (CurrentPop == POP_Status) ? imgINVPBAK : imgINVPBAK2; // Extrapolate the height of the popscreen for smoother movement int height = clamp<int> (PopHeight + FixedMul (r_TicFrac, PopHeightChange), -POP_HEIGHT, 0); xscale = CleanXfac; yscale = CleanYfac; left = screen->GetWidth()/2 - 160*CleanXfac; top = bottom + height * yscale; screen->DrawTexture (Images[back], left, top, DTA_CleanNoMove, true, DTA_Alpha, FRACUNIT*3/4, TAG_DONE); screen->DrawTexture (Images[bars], left, top, DTA_CleanNoMove, true, TAG_DONE); screen->SetFont (SmallFont2); switch (CurrentPop) { case POP_Log: // Draw the latest log message. sprintf (buff, "%02d:%02d:%02d", (level.time/TICRATE)/3600, ((level.time/TICRATE)%3600)/60, (level.time/TICRATE)%60); screen->DrawText (CR_UNTRANSLATED, left+210*xscale, top+8*yscale, buff, DTA_CleanNoMove, true, TAG_DONE); if (CPlayer->LogText != NULL) { brokenlines_t *lines = V_BreakLines (272, CPlayer->LogText); for (i = 0; lines[i].width >= 0; ++i) { screen->DrawText (CR_UNTRANSLATED, left+24*xscale, top+(18+i*12)*yscale, lines[i].string, DTA_CleanNoMove, true, TAG_DONE); } V_FreeBrokenLines (lines); } break; case POP_Keys: // List the keys the player has. int pos, endpos, leftcol; int clipleft, clipright; pos = KeyPopPos; endpos = pos + 10; leftcol = 20; clipleft = left + 17*xscale; clipright = left + (320-17)*xscale; if (KeyPopScroll > 0) { // Extrapolate the scroll position for smoother scrolling int scroll = MAX<int> (0,KeyPopScroll - FixedMul (r_TicFrac, 280/KEY_TIME)); pos -= 10; leftcol = leftcol - 280 + scroll; } for (i = 0, item = CPlayer->mo->Inventory; i < endpos && item != NULL; item = item->Inventory) { if (!item->IsKindOf (RUNTIME_CLASS(AKey))) continue; if (i < pos) { i++; continue; } label = item->GetClass()->Meta.GetMetaString (AMETA_StrifeName); if (label == NULL) { label = item->GetClass()->Name + 1; } int colnum = ((i-pos) / 5) & (KeyPopScroll > 0 ? 3 : 1); int rownum = (i % 5) * 18; screen->DrawTexture (TexMan(item->Icon), left + (colnum * 140 + leftcol)*xscale, top + (6 + rownum)*yscale, DTA_CleanNoMove, true, DTA_ClipLeft, clipleft, DTA_ClipRight, clipright, TAG_DONE); screen->DrawText (CR_UNTRANSLATED, left + (colnum * 140 + leftcol + 17)*xscale, top + (11 + rownum)*yscale, label, DTA_CleanNoMove, true, DTA_ClipLeft, clipleft, DTA_ClipRight, clipright, TAG_DONE); i++; } break; case POP_Status: // Show miscellaneous status items. // Print stats DrINumber2 (CPlayer->accuracy, left+268*xscale, top+28*yscale, 7*xscale, imgFONY0); DrINumber2 (CPlayer->stamina, left+268*xscale, top+52*yscale, 7*xscale, imgFONY0); // How many keys does the player have? for (i = 0, item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory) { if (item->IsKindOf (RUNTIME_CLASS(AKey))) { i++; } } DrINumber2 (i, left+268*xscale, top+76*yscale, 7*xscale, imgFONY0); // Does the player have a communicator? item = CPlayer->mo->FindInventory (RUNTIME_CLASS(ACommunicator)); if (item != NULL) { screen->DrawTexture (TexMan(item->Icon), left + 280*xscale, top + 74*yscale, DTA_CleanNoMove, true, TAG_DONE); } // How much ammo does the player have? static const struct { const TypeInfo *AmmoType; int Y; } AmmoList[7] = { { RUNTIME_CLASS(AClipOfBullets), 19 }, { RUNTIME_CLASS(APoisonBolts), 35 }, { RUNTIME_CLASS(AElectricBolts), 43 }, { RUNTIME_CLASS(AHEGrenadeRounds), 59 }, { RUNTIME_CLASS(APhosphorusGrenadeRounds), 67 }, { RUNTIME_CLASS(AMiniMissiles), 75 }, { RUNTIME_CLASS(AEnergyPod), 83 } }; for (i = 0; i < 7; ++i) { item = CPlayer->mo->FindInventory (AmmoList[i].AmmoType); if (item == NULL) { DrINumber2 (0, left+206*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); DrINumber2 (((AInventory *)GetDefaultByType (AmmoList[i].AmmoType))->MaxAmount, left+239*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); } else { DrINumber2 (item->Amount, left+206*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); DrINumber2 (item->MaxAmount, left+239*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); } } // What weapons does the player have? static const struct { const char *TypeName; int X, Y; } WeaponList[6] = { { "StrifeCrossbow", 23, 19 }, { "AssaultGun", 21, 41 }, { "FlameThrower", 57, 50 }, { "MiniMissileLauncher", 20, 64 }, { "StrifeGrenadeLauncher", 55, 20 }, { "Mauler", 52, 75 }, }; for (i = 0; i < 6; ++i) { item = CPlayer->mo->FindInventory (TypeInfo::FindType (WeaponList[i].TypeName)); if (item != NULL) { screen->DrawTexture (TexMan(item->Icon), left + WeaponList[i].X*xscale, top + WeaponList[i].Y*yscale, DTA_CleanNoMove, true, DTA_LeftOffset, 0, DTA_TopOffset, 0, TAG_DONE); } } break; } screen->SetFont (SmallFont); }
void cht_DoCheat (player_t *player, int cheat) { static const char * const BeholdPowers[9] = { "PowerInvulnerable", "PowerStrength", "PowerInvisibility", "PowerIronFeet", "MapRevealer", "PowerLightAmp", "PowerShadow", "PowerMask", "PowerTargeter", }; PClassActor *type; AInventory *item; const char *msg = ""; char msgbuild[32]; int i; switch (cheat) { case CHT_IDDQD: if (!(player->cheats & CF_GODMODE) && player->playerstate == PST_LIVE) { if (player->mo) player->mo->health = deh.GodHealth; player->health = deh.GodHealth; } // fall through to CHT_GOD case CHT_GOD: player->cheats ^= CF_GODMODE; if (player->cheats & CF_GODMODE) msg = GStrings("STSTR_DQDON"); else msg = GStrings("STSTR_DQDOFF"); ST_SetNeedRefresh(); break; case CHT_BUDDHA: player->cheats ^= CF_BUDDHA; if (player->cheats & CF_BUDDHA) msg = GStrings("TXT_BUDDHAON"); else msg = GStrings("TXT_BUDDHAOFF"); break; case CHT_GOD2: player->cheats ^= CF_GODMODE2; if (player->cheats & CF_GODMODE2) msg = GStrings("STSTR_DQD2ON"); else msg = GStrings("STSTR_DQD2OFF"); ST_SetNeedRefresh(); break; case CHT_BUDDHA2: player->cheats ^= CF_BUDDHA2; if (player->cheats & CF_BUDDHA2) msg = GStrings("TXT_BUDDHA2ON"); else msg = GStrings("TXT_BUDDHA2OFF"); break; case CHT_NOCLIP: player->cheats ^= CF_NOCLIP; if (player->cheats & CF_NOCLIP) msg = GStrings("STSTR_NCON"); else msg = GStrings("STSTR_NCOFF"); break; case CHT_NOCLIP2: player->cheats ^= CF_NOCLIP2; if (player->cheats & CF_NOCLIP2) { player->cheats |= CF_NOCLIP; msg = GStrings("STSTR_NC2ON"); } else { player->cheats &= ~CF_NOCLIP; msg = GStrings("STSTR_NCOFF"); } if (player->mo->Vel.X == 0) player->mo->Vel.X = MinVel; // force some lateral movement so that internal variables are up to date break; case CHT_NOVELOCITY: player->cheats ^= CF_NOVELOCITY; if (player->cheats & CF_NOVELOCITY) msg = GStrings("TXT_LEADBOOTSON"); else msg = GStrings("TXT_LEADBOOTSOFF"); break; case CHT_FLY: if (player->mo != NULL) { player->mo->flags7 ^= MF7_FLYCHEAT; if (player->mo->flags7 & MF7_FLYCHEAT) { player->mo->flags |= MF_NOGRAVITY; player->mo->flags2 |= MF2_FLY; msg = GStrings("TXT_LIGHTER"); } else { player->mo->flags &= ~MF_NOGRAVITY; player->mo->flags2 &= ~MF2_FLY; msg = GStrings("TXT_GRAVITY"); } } break; case CHT_MORPH: msg = cht_Morph (player, static_cast<PClassPlayerPawn *>(PClass::FindClass (gameinfo.gametype == GAME_Heretic ? NAME_ChickenPlayer : NAME_PigPlayer)), true); break; case CHT_NOTARGET: player->cheats ^= CF_NOTARGET; if (player->cheats & CF_NOTARGET) msg = "notarget ON"; else msg = "notarget OFF"; break; case CHT_ANUBIS: player->cheats ^= CF_FRIGHTENING; if (player->cheats & CF_FRIGHTENING) msg = "\"Quake with fear!\""; else msg = "No more ogre armor"; break; case CHT_CHASECAM: player->cheats ^= CF_CHASECAM; if (player->cheats & CF_CHASECAM) msg = "chasecam ON"; else msg = "chasecam OFF"; R_ResetViewInterpolation (); break; case CHT_CHAINSAW: if (player->mo != NULL && player->health >= 0) { type = PClass::FindActor("Chainsaw"); if (player->mo->FindInventory (type) == NULL) { player->mo->GiveInventoryType (type); } msg = GStrings("STSTR_CHOPPERS"); } // [RH] The original cheat also set powers[pw_invulnerability] to true. // Since this is a timer and not a boolean, it effectively turned off // the invulnerability powerup, although it looks like it was meant to // turn it on. break; case CHT_POWER: if (player->mo != NULL && player->health >= 0) { item = player->mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2), true); if (item != NULL) { item->Destroy (); msg = GStrings("TXT_CHEATPOWEROFF"); } else { player->mo->GiveInventoryType (RUNTIME_CLASS(APowerWeaponLevel2)); msg = GStrings("TXT_CHEATPOWERON"); } } break; case CHT_IDKFA: cht_Give (player, "backpack"); cht_Give (player, "weapons"); cht_Give (player, "ammo"); cht_Give (player, "keys"); cht_Give (player, "armor"); msg = GStrings("STSTR_KFAADDED"); break; case CHT_IDFA: cht_Give (player, "backpack"); cht_Give (player, "weapons"); cht_Give (player, "ammo"); cht_Give (player, "armor"); msg = GStrings("STSTR_FAADDED"); break; case CHT_BEHOLDV: case CHT_BEHOLDS: case CHT_BEHOLDI: case CHT_BEHOLDR: case CHT_BEHOLDA: case CHT_BEHOLDL: case CHT_PUMPUPI: case CHT_PUMPUPM: case CHT_PUMPUPT: i = cheat - CHT_BEHOLDV; if (i == 4) { level.flags2 ^= LEVEL2_ALLMAP; } else if (player->mo != NULL && player->health >= 0) { item = player->mo->FindInventory(PClass::FindActor(BeholdPowers[i])); if (item == NULL) { if (i != 0) { cht_Give(player, BeholdPowers[i]); if (cheat == CHT_BEHOLDS) { P_GiveBody (player->mo, -100); } } else { // Let's give the item here so that the power doesn't need colormap information. cht_Give(player, "InvulnerabilitySphere"); } } else { item->Destroy (); } } msg = GStrings("STSTR_BEHOLDX"); break; case CHT_MASSACRE: { int killcount = P_Massacre (); // killough 3/22/98: make more intelligent about plural // Ty 03/27/98 - string(s) *not* externalized mysnprintf (msgbuild, countof(msgbuild), "%d Monster%s Killed", killcount, killcount==1 ? "" : "s"); msg = msgbuild; } break; case CHT_HEALTH: if (player->mo != NULL && player->playerstate == PST_LIVE) { player->health = player->mo->health = player->mo->GetDefault()->health; msg = GStrings("TXT_CHEATHEALTH"); } break; case CHT_KEYS: cht_Give (player, "keys"); msg = GStrings("TXT_CHEATKEYS"); break; // [GRB] case CHT_RESSURECT: if (player->playerstate != PST_LIVE && player->mo != nullptr) { if (player->mo->IsKindOf(RUNTIME_CLASS(APlayerChunk))) { Printf("Unable to resurrect. Player is no longer connected to its body.\n"); } else { player->playerstate = PST_LIVE; player->health = player->mo->health = player->mo->GetDefault()->health; player->viewheight = ((APlayerPawn *)player->mo->GetDefault())->ViewHeight; player->mo->flags = player->mo->GetDefault()->flags; player->mo->flags2 = player->mo->GetDefault()->flags2; player->mo->flags3 = player->mo->GetDefault()->flags3; player->mo->flags4 = player->mo->GetDefault()->flags4; player->mo->flags5 = player->mo->GetDefault()->flags5; player->mo->flags6 = player->mo->GetDefault()->flags6; player->mo->flags7 = player->mo->GetDefault()->flags7; player->mo->renderflags &= ~RF_INVISIBLE; player->mo->Height = player->mo->GetDefault()->Height; player->mo->radius = player->mo->GetDefault()->radius; player->mo->special1 = 0; // required for the Hexen fighter's fist attack. // This gets set by AActor::Die as flag for the wimpy death and must be reset here. player->mo->SetState (player->mo->SpawnState); if (!(player->mo->flags2 & MF2_DONTTRANSLATE)) { player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players)); } player->mo->DamageType = NAME_None; if (player->ReadyWeapon != nullptr) { P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetUpState()); } if (player->morphTics > 0) { P_UndoPlayerMorph(player, player); } } } break; case CHT_GIMMIEA: cht_Give (player, "ArtiInvulnerability"); msg = "Valador's Ring of Invunerability"; break; case CHT_GIMMIEB: cht_Give (player, "ArtiInvisibility"); msg = "Shadowsphere"; break; case CHT_GIMMIEC: cht_Give (player, "ArtiHealth"); msg = "Quartz Flask"; break; case CHT_GIMMIED: cht_Give (player, "ArtiSuperHealth"); msg = "Mystic Urn"; break; case CHT_GIMMIEE: cht_Give (player, "ArtiTomeOfPower"); msg = "Tyketto's Tome of Power"; break; case CHT_GIMMIEF: cht_Give (player, "ArtiTorch"); msg = "Torch"; break; case CHT_GIMMIEG: cht_Give (player, "ArtiTimeBomb"); msg = "Delmintalintar's Time Bomb of the Ancients"; break; case CHT_GIMMIEH: cht_Give (player, "ArtiEgg"); msg = "Torpol's Morph Ovum"; break; case CHT_GIMMIEI: cht_Give (player, "ArtiFly"); msg = "Inhilicon's Wings of Wrath"; break; case CHT_GIMMIEJ: cht_Give (player, "ArtiTeleport"); msg = "Darchala's Chaos Device"; break; case CHT_GIMMIEZ: for (int i=0; i<16; i++) { cht_Give (player, "artifacts"); } msg = "All artifacts!"; break; case CHT_TAKEWEAPS: if (player->morphTics || player->mo == NULL || player->mo->health <= 0) { return; } { // Take away all weapons that are either non-wimpy or use ammo. AInventory **invp = &player->mo->Inventory, **lastinvp; for (item = *invp; item != NULL; item = *invp) { lastinvp = invp; invp = &(*invp)->Inventory; if (item->IsKindOf (RUNTIME_CLASS(AWeapon))) { AWeapon *weap = static_cast<AWeapon *> (item); if (!(weap->WeaponFlags & WIF_WIMPY_WEAPON) || weap->AmmoType1 != NULL) { item->Destroy (); invp = lastinvp; } } } } msg = GStrings("TXT_CHEATIDKFA"); break; case CHT_NOWUDIE: cht_Suicide (player); msg = GStrings("TXT_CHEATIDDQD"); break; case CHT_ALLARTI: for (int i=0; i<25; i++) { cht_Give (player, "artifacts"); } msg = GStrings("TXT_CHEATARTIFACTS3"); break; case CHT_PUZZLE: cht_Give (player, "puzzlepieces"); msg = GStrings("TXT_CHEATARTIFACTS3"); break; case CHT_MDK: if (player->mo == NULL) { Printf ("What do you want to kill outside of a game?\n"); } else if (!deathmatch) { // Don't allow this in deathmatch even with cheats enabled, because it's // a very very cheap kill. P_LineAttack (player->mo, player->mo->Angles.Yaw, PLAYERMISSILERANGE, P_AimLineAttack (player->mo, player->mo->Angles.Yaw, PLAYERMISSILERANGE), TELEFRAG_DAMAGE, NAME_MDK, NAME_BulletPuff); } break; case CHT_DONNYTRUMP: cht_Give (player, "HealthTraining"); msg = GStrings("TXT_MIDASTOUCH"); break; case CHT_LEGO: if (player->mo != NULL && player->health >= 0) { int oldpieces = ASigil::GiveSigilPiece (player->mo); item = player->mo->FindInventory (RUNTIME_CLASS(ASigil)); if (item != NULL) { if (oldpieces == 5) { item->Destroy (); } else { player->PendingWeapon = static_cast<AWeapon *> (item); } } } break; case CHT_PUMPUPH: cht_Give (player, "MedPatch"); cht_Give (player, "MedicalKit"); cht_Give (player, "SurgeryKit"); msg = GStrings("TXT_GOTSTUFF"); break; case CHT_PUMPUPP: cht_Give (player, "AmmoSatchel"); msg = GStrings("TXT_GOTSTUFF"); break; case CHT_PUMPUPS: cht_Give (player, "UpgradeStamina", 10); cht_Give (player, "UpgradeAccuracy"); msg = GStrings("TXT_GOTSTUFF"); break; case CHT_CLEARFROZENPROPS: player->cheats &= ~(CF_FROZEN|CF_TOTALLYFROZEN); msg = "Frozen player properties turned off"; break; case CHT_FREEZE: bglobal.changefreeze ^= 1; if (bglobal.freeze ^ bglobal.changefreeze) { msg = GStrings("TXT_FREEZEON"); } else { msg = GStrings("TXT_FREEZEOFF"); } break; } if (!*msg) // [SO] Don't print blank lines! return; if (player == &players[consoleplayer]) Printf ("%s\n", msg); else if (cheat != CHT_CHASECAM) Printf ("%s cheats: %s\n", player->userinfo.GetName(), msg); }
bool P_CheckKeys (AActor *owner, int keynum, bool remote) { const char *failtext; const char *failsound; DWORD keymask; AInventory *item; failtext = NULL; failsound = NULL; switch (keynum) { case 0: // Key 0 is like a psuedo-key. Everything pretends to have it, so it // can act as a no-key-needed flag. return true; case OnlyInRetail: failtext = "THIS AREA IS ONLY AVAILABLE IN THE RETAIL VERSION OF STRIFE"; break; case ThatDoesntWork: failtext = "That doesn't seem to work"; break; case AllKeys: case All3Keys: if (gameinfo.gametype == GAME_Strife) { // Strife has 26 (actually 27) different keys, so I am not // going to implement the AllKeys check for Strife. failtext = "That doesn't seem to work"; break; } // Intentional fall-through default: keymask = 0; // See if the owner is holding a matching key. for (item = owner->Inventory; item != NULL; item = item->Inventory) { if (item->IsKindOf (RUNTIME_CLASS(AKey))) { AKey *key = static_cast<AKey *> (item); if (keynum == AnyKey) { return true; } else if ((keynum & 0x7f) == AllKeys) { keymask |= 1 << (key->KeyNumber - 1); } else if (key->KeyNumber == keynum || key->AltKeyNumber == keynum) { return true; } } } if ((keynum & 0x7f) == AllKeys) { // The check for holding "all keys" is only made against the // standard keys and not any custom user-added keys. switch (gameinfo.gametype) { case GAME_Doom: if (keynum & 0x80) { // Cards and skulls are treated the same keymask |= keymask >> 3; keymask |= keymask << 3; } if ((keymask & (1|2|4|8|16|32)) == (1|2|4|8|16|32)) { return true; } failtext = (keynum & 0x80) ? GStrings("PD_ALL3") : GStrings("PD_ALL6"); break; case GAME_Heretic: if ((keymask & (1|2|4)) == (1|2|4)) { return true; } failtext = GStrings("PD_ALL3"); break; case GAME_Hexen: if ((keymask & ((1<<11)-1)) == ((1<<11)-1)) { return true; } failtext = "You need all the keys"; break; default: // The other enumerations won't reach this switch, but make GCC happy. failtext = "That doesn't seem to work"; break; } } break; }
bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntype, int duration, int style, PClassActor *enter_flash, PClassActor *exit_flash) { AInventory *item; APlayerPawn *morphed; APlayerPawn *actor; actor = p->mo; if (actor == NULL) { return false; } if (actor->flags3 & MF3_DONTMORPH) { return false; } if ((p->mo->flags2 & MF2_INVULNERABLE) && ((p != activator) || (!(style & MORPH_WHENINVULNERABLE)))) { // Immune when invulnerable unless this is a power we activated return false; } if (p->morphTics) { // Player is already a beast if ((p->mo->GetClass() == spawntype) && (p->mo->PlayerFlags & PPF_CANSUPERMORPH) && (p->morphTics < (((duration) ? duration : MORPHTICS) - TICRATE)) && (p->mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2), true) == NULL)) { // Make a super chicken p->mo->GiveInventoryType (RUNTIME_CLASS(APowerWeaponLevel2)); } return false; } if (p->health <= 0) { // Dead players cannot morph return false; } if (spawntype == NULL) { return false; } if (!spawntype->IsDescendantOf (RUNTIME_CLASS(APlayerPawn))) { return false; } if (spawntype == p->mo->GetClass()) { return false; } morphed = static_cast<APlayerPawn *>(Spawn (spawntype, actor->Pos(), NO_REPLACE)); EndAllPowerupEffects(actor->Inventory); DObject::StaticPointerSubstitution (actor, morphed); if ((actor->tid != 0) && (style & MORPH_NEWTIDBEHAVIOUR)) { morphed->tid = actor->tid; morphed->AddToHash (); actor->RemoveFromHash (); actor->tid = 0; } morphed->angle = actor->angle; morphed->target = actor->target; morphed->tracer = actor; morphed->Score = actor->Score; p->PremorphWeapon = p->ReadyWeapon; morphed->special2 = actor->flags & ~MF_JUSTHIT; morphed->player = p; if (actor->renderflags & RF_INVISIBLE) { morphed->special2 |= MF_JUSTHIT; } if (morphed->ViewHeight > p->viewheight && p->deltaviewheight == 0) { // If the new view height is higher than the old one, start moving toward it. p->deltaviewheight = p->GetDeltaViewHeight(); } morphed->flags |= actor->flags & (MF_SHADOW|MF_NOGRAVITY); morphed->flags2 |= actor->flags2 & MF2_FLY; morphed->flags3 |= actor->flags3 & MF3_GHOST; AActor *eflash = Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->PosPlusZ(TELEFOGHEIGHT), ALLOW_REPLACE); actor->player = NULL; actor->flags &= ~(MF_SOLID|MF_SHOOTABLE); actor->flags |= MF_UNMORPHED; actor->renderflags |= RF_INVISIBLE; p->morphTics = (duration) ? duration : MORPHTICS; // [MH] Used by SBARINFO to speed up face drawing p->MorphedPlayerClass = spawntype; p->MorphStyle = style; p->MorphExitFlash = (exit_flash) ? exit_flash : RUNTIME_CLASS(ATeleportFog); p->health = morphed->health; p->mo = morphed; p->velx = p->vely = 0; morphed->ObtainInventory (actor); // Remove all armor for (item = morphed->Inventory; item != NULL; ) { AInventory *next = item->Inventory; if (item->IsKindOf (RUNTIME_CLASS(AArmor))) { if (item->IsKindOf (RUNTIME_CLASS(AHexenArmor))) { // Set the HexenArmor slots to 0, except the class slot. AHexenArmor *hxarmor = static_cast<AHexenArmor *>(item); hxarmor->Slots[0] = 0; hxarmor->Slots[1] = 0; hxarmor->Slots[2] = 0; hxarmor->Slots[3] = 0; hxarmor->Slots[4] = spawntype->HexenArmor[0]; } else { item->DepleteOrDestroy(); } } item = next; } InitAllPowerupEffects(morphed->Inventory); morphed->ActivateMorphWeapon (); if (p->camera == actor) { p->camera = morphed; } morphed->ScoreIcon = actor->ScoreIcon; // [GRB] if (eflash) eflash->target = p->mo; return true; }
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; }
bool AWeaponPiece::TryPickup (AActor *&toucher) { AInventory * inv; AWeaponHolder * hold=NULL; bool shouldStay = PrivateShouldStay (); int gaveAmmo; AWeapon * Defaults=(AWeapon*)GetDefaultByType(WeaponClass); FullWeapon=NULL; for(inv=toucher->Inventory;inv;inv=inv->Inventory) { if (inv->IsKindOf(RUNTIME_CLASS(AWeaponHolder))) { hold=static_cast<AWeaponHolder*>(inv); if (hold->PieceWeapon==WeaponClass) break; hold=NULL; } } if (!hold) { hold=static_cast<AWeaponHolder*>(Spawn(RUNTIME_CLASS(AWeaponHolder), 0, 0, 0, NO_REPLACE)); hold->BecomeItem(); hold->AttachToOwner(toucher); hold->PieceMask=0; hold->PieceWeapon=WeaponClass; } if (shouldStay) { // Cooperative net-game if (hold->PieceMask & PieceValue) { // Already has the piece return false; } toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1); toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2); } else { // Deathmatch or singleplayer game gaveAmmo = toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1) + toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2); if (hold->PieceMask & PieceValue) { // Already has the piece, check if mana needed if (!gaveAmmo) return false; GoAwayAndDie(); return true; } } hold->PieceMask |= PieceValue; // Check if weapon assembled if (hold->PieceMask== (1<<Defaults->health)-1) { if (!toucher->FindInventory (WeaponClass)) { FullWeapon= static_cast<AWeapon*>(Spawn(WeaponClass, 0, 0, 0, NO_REPLACE)); // The weapon itself should not give more ammo to the player! FullWeapon->AmmoGive1=0; FullWeapon->AmmoGive2=0; FullWeapon->AttachToOwner(toucher); FullWeapon->AmmoGive1=Defaults->AmmoGive1; FullWeapon->AmmoGive2=Defaults->AmmoGive2; } } GoAwayAndDie(); return true; }