static void TakeStrifeItem (const TypeInfo *itemtype, int amount) { if (itemtype == NULL || amount == 0) return; // Don't take quest items. if (itemtype->IsDescendantOf (RUNTIME_CLASS(AQuestItem))) return; // Don't take keys if (itemtype->IsDescendantOf (RUNTIME_CLASS(AKey))) return; // Don't take the sigil if (itemtype == RUNTIME_CLASS(ASigil)) return; AInventory *item = ConversationPC->FindInventory (itemtype); if (item != NULL) { item->Amount -= amount; if (item->Amount <= 0) { item->Destroy (); } } }
static void TakeStrifeItem (player_t *player, const PClass *itemtype, int amount) { if (itemtype == NULL || amount == 0) return; // Don't take quest items. if (itemtype->IsDescendantOf (PClass::FindClass(NAME_QuestItem))) return; // Don't take keys. if (itemtype->IsDescendantOf (RUNTIME_CLASS(AKey))) return; // Don't take the sigil. if (itemtype == RUNTIME_CLASS(ASigil)) return; AInventory *item = player->mo->FindInventory (itemtype); if (item != NULL) { item->Amount -= amount; if (item->Amount <= 0) { item->Destroy (); } } }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveQuestItem) { ACTION_PARAM_START(1); ACTION_PARAM_INT(questitem, 0); // Give one of these quest items to every player in the game for (int i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i]) { AInventory *item = static_cast<AInventory *>(Spawn (QuestItemClasses[questitem-1], 0,0,0, NO_REPLACE)); if (!item->CallTryPickup (players[i].mo)) { item->Destroy (); } } } char messageid[64]; mysnprintf(messageid, countof(messageid), "TXT_QUEST_%d", questitem); const char * name = GStrings[messageid]; if (name != NULL) { C_MidPrint (SmallFont, name); } }
void AMinotaurFriend::Die (AActor *source, AActor *inflictor, int dmgflags) { Super::Die (source, inflictor, dmgflags); if (tracer && tracer->health > 0 && tracer->player) { // Search thinker list for minotaur TThinkerIterator<AMinotaurFriend> iterator; AMinotaurFriend *mo; while ((mo = iterator.Next()) != NULL) { if (mo->health <= 0) continue; // [RH] Minotaurs can't be morphed, so this isn't needed //if (!(mo->flags&MF_COUNTKILL)) continue; // for morphed minotaurs if (mo->flags&MF_CORPSE) continue; if (mo->StartTime >= 0 && (level.maptime - StartTime) >= MAULATORTICS) continue; if (mo->tracer != NULL && mo->tracer->player == tracer->player) break; } if (mo == NULL) { AInventory *power = tracer->FindInventory(PClass::FindActor("PowerMinotaur")); if (power != NULL) { power->Destroy (); } } } }
void GiveSpawner (player_t *player, const PClass *type, int amount) { if (player->mo == NULL || player->health <= 0) { return; } AInventory *item = static_cast<AInventory *> (Spawn (type, player->mo->x, player->mo->y, player->mo->z, NO_REPLACE)); if (item != NULL) { if (amount > 0) { if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup))) { if (static_cast<ABasicArmorPickup*>(item)->SaveAmount != 0) { static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount; } else { static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount; } } else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))) { static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount; // [BB] static_cast<ABasicArmorBonus*>(item)->BonusCount *= amount; } else { item->Amount = MIN (amount, item->MaxAmount); } } if(item->flags & MF_COUNTITEM) // Given items shouldn't count against the map's total, { // since they aren't added to the player's total. level.total_items--; item->flags &= ~MF_COUNTITEM; } if (!item->CallTryPickup (player->mo)) { item->Destroy (); } else { // [BB] This construction is more or less a hack, but at least the give cheats are now working. SERVER_GiveInventoryToPlayer( player, item ); // [BC] Play the announcer sound. if ( players[consoleplayer].camera == players[consoleplayer].mo && cl_announcepickups ) ANNOUNCER_PlayEntry( cl_announcer, item->PickupAnnouncerEntry( )); } } }
bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) { TObjPtr<AInventory> Invstack = Inventory; // A pointer of the inventories item stack. // unmorphed versions of a currently morphed actor cannot pick up anything. if (toucher->flags & MF_UNMORPHED) return false; bool res; if (CanPickup(toucher)) res = TryPickup(toucher); else if (!(ItemFlags & IF_RESTRICTABSOLUTELY)) res = TryPickupRestricted(toucher); // let an item decide for itself how it will handle this else return false; // Morph items can change the toucher so we need an option to return this info. if (toucher_return != NULL) *toucher_return = toucher; if (!res && (ItemFlags & IF_ALWAYSPICKUP) && !ShouldStay()) { res = true; GoAwayAndDie(); } if (res) { GiveQuest(toucher); // Transfer all inventory accross that the old object had, if requested. if ((ItemFlags & IF_TRANSFER)) { while (Invstack) { AInventory* titem = Invstack; Invstack = titem->Inventory; if (titem->Owner == this) { if (!titem->CallTryPickup(toucher)) // The object no longer can exist { titem->Destroy(); } } } } } return res; }
bool AHealthTraining::TryPickup (AActor *&toucher) { if (Super::TryPickup (toucher)) { toucher->GiveInventoryType (PClass::FindActor("GunTraining")); AInventory *coin = Spawn<ACoin> (); if (coin != NULL) { coin->Amount = toucher->player->mo->accuracy*5 + 300; if (!coin->CallTryPickup (toucher)) { coin->Destroy (); } } return true; } return false; }
void GiveSpawner (player_t *player, PClassInventory *type, int amount) { if (player->mo == NULL || player->health <= 0) { return; } AInventory *item = static_cast<AInventory *> (Spawn (type, player->mo->Pos(), NO_REPLACE)); if (item != NULL) { if (amount > 0) { if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup))) { if (static_cast<ABasicArmorPickup*>(item)->SaveAmount != 0) { static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount; } else { static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount; } } else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))) { static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount; } else { item->Amount = MIN (amount, item->MaxAmount); } } item->ClearCounters(); if (!item->CallTryPickup (player->mo)) { item->Destroy (); } } }
static void PickConversationReply () { const char *replyText = NULL; FStrifeDialogueReply *reply = (FStrifeDialogueReply *)ConversationItems[ConversationMenu.lastOn].c.extra; bool takestuff; int i; M_ClearMenus (); CleanupConversationMenu (); if (reply == NULL) { return; } // Check if you have the requisite items for this choice for (i = 0; i < 3; ++i) { if (!CheckStrifeItem (reply->ItemCheck[i], reply->ItemCheckAmount[i])) { // No, you don't. Say so and let the NPC animate negatively. if (reply->QuickNo) { Printf ("%s\n", reply->QuickNo); } ConversationNPC->ConversationAnimation (2); return; } } // Yay, you do! Let the NPC animate affirmatively. ConversationNPC->ConversationAnimation (1); // If this reply gives you something, then try to receive it. takestuff = true; if (reply->GiveType != NULL) { AInventory *item = static_cast<AInventory *> (Spawn (reply->GiveType, 0, 0, 0)); // Items given here should not count as items! if (item->flags & MF_COUNTITEM) { level.total_items--; item->flags &= ~MF_COUNTITEM; } item->flags |= MF_DROPPED; if (!item->TryPickup (players[consoleplayer].mo)) { item->Destroy (); takestuff = false; } } // Take away required items if the give was successful or none was needed. if (takestuff) { for (i = 0; i < 3; ++i) { TakeStrifeItem (reply->ItemCheck[i], reply->ItemCheckAmount[i]); } replyText = reply->QuickYes; } else { replyText = "You seem to have enough!"; } // Update the quest log, if needed. if (reply->LogNumber != 0) { players[consoleplayer].SetLogNumber (reply->LogNumber); } // Does this reply alter the speaker's conversation node? If NextNode is positive, // the next time they talk, the will show the new node. If it is negative, then they // will show the new node right away without terminating the dialogue. if (reply->NextNode != 0) { int rootnode = FindNode (ConversationNPC->GetDefault()->Conversation); if (reply->NextNode < 0) { ConversationNPC->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1]; if (gameaction != ga_slideshow) { P_StartConversation (ConversationNPC, players[consoleplayer].mo); return; } else { S_StopSound (ConversationNPC, CHAN_VOICE); } } else { ConversationNPC->Conversation = StrifeDialogues[rootnode + reply->NextNode - 1]; } } if (replyText != NULL) { Printf ("%s\n", replyText); } ConversationNPC->angle = ConversationNPCAngle; }
bool AInventory::TryPickup (AActor *&toucher) { AActor *newtoucher = toucher; // in case changed by the powerup // If HandlePickup() returns true, it will set the IF_PICKUPGOOD flag // to indicate that this item has been picked up. If the item cannot be // picked up, then it leaves the flag cleared. ItemFlags &= ~IF_PICKUPGOOD; if (toucher->Inventory != NULL && toucher->Inventory->HandlePickup (this)) { // Let something else the player is holding intercept the pickup. if (!(ItemFlags & IF_PICKUPGOOD)) { return false; } ItemFlags &= ~IF_PICKUPGOOD; GoAwayAndDie (); } else if (MaxAmount == 0 && !IsKindOf(RUNTIME_CLASS(AAmmo))) { // Special case: If an item's MaxAmount is 0, you can still pick it // up if it is autoactivate-able. if (!(ItemFlags & IF_AUTOACTIVATE)) { return false; } // The item is placed in the inventory just long enough to be used. toucher->AddInventory (this); bool usegood = Use (true); toucher->RemoveInventory (this); if (usegood) { GoAwayAndDie (); } else { return false; } } else { // Add the item to the inventory. It is not already there, or HandlePickup // would have already taken care of it. AInventory *copy = CreateCopy (toucher); if (copy == NULL) { return false; } // Some powerups cannot activate absolutely, for // example, PowerMorph; fail the pickup if so. if (copy->ItemFlags & IF_INITEFFECTFAILED) { if (copy != this) copy->Destroy(); else ItemFlags &= ~IF_INITEFFECTFAILED; return false; } // Handle owner-changing powerups if (copy->ItemFlags & IF_CREATECOPYMOVED) { newtoucher = copy->Owner; copy->Owner = NULL; copy->ItemFlags &= ~IF_CREATECOPYMOVED; } // Continue onwards with the rest copy->AttachToOwner (newtoucher); if (ItemFlags & IF_AUTOACTIVATE) { if (copy->Use (true)) { if (--copy->Amount <= 0) { copy->flags &= ~MF_SPECIAL; copy->SetState (copy->FindState("HoldAndDestroy")); } } } } return true; }
void cht_Take (player_t *player, const char *name, int amount) { bool takeall; PClassActor *type; if (player->mo == NULL || player->health <= 0) { return; } takeall = (stricmp (name, "all") == 0); if (!takeall && stricmp (name, "health") == 0) { if (player->mo->health - amount <= 0 || player->health - amount <= 0 || amount == 0) { cht_Suicide (player); if (player == &players[consoleplayer]) C_HideConsole (); return; } if (amount > 0) { if (player->mo) { player->mo->health -= amount; player->health = player->mo->health; } else { player->health -= amount; } } if (!takeall) return; } if (takeall || stricmp (name, "backpack") == 0) { // Take away all types of backpacks the player might own. for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { PClass *type = PClassActor::AllActorClasses[i]; if (type->IsDescendantOf(RUNTIME_CLASS (ABackpackItem))) { AInventory *pack = player->mo->FindInventory(static_cast<PClassActor *>(type)); if (pack) pack->Destroy(); } } if (!takeall) return; } if (takeall || stricmp (name, "ammo") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { PClass *type = PClassActor::AllActorClasses[i]; if (type->ParentClass == RUNTIME_CLASS (AAmmo)) { AInventory *ammo = player->mo->FindInventory(static_cast<PClassActor *>(type)); if (ammo) ammo->DepleteOrDestroy(); } } if (!takeall) return; } if (takeall || stricmp (name, "armor") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { type = PClassActor::AllActorClasses[i]; if (type->IsDescendantOf (RUNTIME_CLASS (AArmor))) { AInventory *armor = player->mo->FindInventory(static_cast<PClassActor *>(type)); if (armor) armor->DepleteOrDestroy(); } } if (!takeall) return; } if (takeall || stricmp (name, "keys") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { type = PClassActor::AllActorClasses[i]; if (type->IsDescendantOf (RUNTIME_CLASS (AKey))) { AActor *key = player->mo->FindInventory(static_cast<PClassActor *>(type)); if (key) key->Destroy (); } } if (!takeall) return; } if (takeall || stricmp (name, "weapons") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { type = PClassActor::AllActorClasses[i]; if (type != RUNTIME_CLASS(AWeapon) && type->IsDescendantOf (RUNTIME_CLASS (AWeapon))) { AActor *weapon = player->mo->FindInventory(static_cast<PClassActor *>(type)); if (weapon) weapon->Destroy (); player->ReadyWeapon = nullptr; player->PendingWeapon = WP_NOCHANGE; } } if (!takeall) return; } if (takeall || stricmp (name, "artifacts") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { type = PClassActor::AllActorClasses[i]; if (type->IsDescendantOf (RUNTIME_CLASS (AInventory))) { if (!type->IsDescendantOf (RUNTIME_CLASS (APuzzleItem)) && !type->IsDescendantOf (RUNTIME_CLASS (APowerup)) && !type->IsDescendantOf (RUNTIME_CLASS (AArmor)) && !type->IsDescendantOf (RUNTIME_CLASS (AWeapon)) && !type->IsDescendantOf (RUNTIME_CLASS (AKey))) { AActor *artifact = player->mo->FindInventory(static_cast<PClassActor *>(type)); if (artifact) artifact->Destroy (); } } } if (!takeall) return; } if (takeall || stricmp (name, "puzzlepieces") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { type = PClassActor::AllActorClasses[i]; if (type->IsDescendantOf (RUNTIME_CLASS (APuzzleItem))) { AActor *puzzlepiece = player->mo->FindInventory(static_cast<PClassActor *>(type)); if (puzzlepiece) puzzlepiece->Destroy (); } } if (!takeall) return; } if (takeall) return; type = PClass::FindActor (name); if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS (AInventory))) { if (player == &players[consoleplayer]) Printf ("Unknown item \"%s\"\n", name); } else { player->mo->TakeInventory(type, amount ? amount : 1); } return; }
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_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 P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, int duration, int style, const PClass *enter_flash, const PClass *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->x, actor->y, actor->z, NO_REPLACE)); 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; Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + 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->Meta.GetMetaFixed (APMETA_Hexenarmor0); } else if (item->ItemFlags & IF_KEEPDEPLETED) { // Set depletable armor to 0 (this includes BasicArmor). item->Amount = 0; } else { item->Destroy (); } } item = next; } morphed->ActivateMorphWeapon (); if (p->camera == actor) { p->camera = morphed; } morphed->ScoreIcon = actor->ScoreIcon; // [GRB] return true; }
void P_AutoUseHealth(player_t *player, int saveHealth) { int i; int count; const TypeInfo *normalType = TypeInfo::FindType ("ArtiHealth"); const TypeInfo *superType = TypeInfo::FindType ("ArtiSuperHealth"); AInventory *normalItem = player->mo->FindInventory (normalType); AInventory *superItem = player->mo->FindInventory (superType); int normalAmount, superAmount; normalAmount = normalItem != NULL ? normalItem->Amount : 0; superAmount = superItem != NULL ? superItem->Amount : 0; if ((gameskill == sk_baby) && (normalAmount*25 >= saveHealth)) { // Use quartz flasks count = (saveHealth+24)/25; for(i = 0; i < count; i++) { player->health += 25; if (--normalItem->Amount == 0) { normalItem->Destroy (); break; } } } else if (superAmount*100 >= saveHealth) { // Use mystic urns count = (saveHealth+99)/100; for(i = 0; i < count; i++) { player->health += 100; if (--superItem->Amount == 0) { superItem->Destroy (); break; } } } else if ((gameskill == sk_baby) && (superAmount*100+normalAmount*25 >= saveHealth)) { // Use mystic urns and quartz flasks count = (saveHealth+24)/25; saveHealth -= count*25; for(i = 0; i < count; i++) { player->health += 25; if (--normalItem->Amount == 0) { normalItem->Destroy (); break; } } count = (saveHealth+99)/100; for(i = 0; i < count; i++) { player->health += 100; if (--superItem->Amount == 0) { superItem->Destroy (); break; } } } player->mo->health = player->health; }