Beispiel #1
0
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);
		}
	}
}
Beispiel #2
0
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));
			}
		}
	}
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
		}
	}
}
Beispiel #5
0
	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;
		}
	}
Beispiel #7
0
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;
}
Beispiel #8
0
//
// 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));
	}
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
	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);
	}
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_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;
	}
Beispiel #14
0
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;
}
Beispiel #15
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;
}
Beispiel #16
0
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;
}