Beispiel #1
0
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 ();
		}
	}
}
Beispiel #2
0
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 ();
		}
	}
}
Beispiel #3
0
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);
	}
}
Beispiel #4
0
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 ();
            }
        }
    }
}
Beispiel #5
0
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( ));
		}
	}
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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 ();
		}
	}
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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);
}
Beispiel #13
0
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;
}
Beispiel #15
0
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;
}