//************************************************************************** //** //** ## ## ## ## ## #### #### ### ### //** ## ## ## ## ## ## ## ## ## ## #### #### //** ## ## ## ## ## ## ## ## ## ## ## ## ## ## //** ## ## ######## ## ## ## ## ## ## ## ### ## //** ### ## ## ### ## ## ## ## ## ## //** # ## ## # #### #### ## ## //** //** $Id: Inventory.vc 2675 2007-08-27 17:45:50Z dj_jl $ //** //** Copyright (C) 1999-2006 Jānis Legzdiņš //** //** This program is free software; you can redistribute it and/or //** modify it under the terms of the GNU General Public License //** as published by the Free Software Foundation; either version 2 //** of the License, or (at your option) any later version. //** //** This program is distributed in the hope that it will be useful, //** but WITHOUT ANY WARRANTY; without even the implied warranty of //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //** GNU General Public License for more details. //** //************************************************************************** //** //** Base class for all items that a player can carry. //** //************************************************************************** class Inventory : ScriptedEntity abstract; const float BONUSADD = 0.2; const int DefMaxAmount = -2; // Special values for powerup's blend colour. const int INVERSECOLOUR = 0x00123456; const int INVERSECOLOURMAP = 32; int Amount; int MaxAmount; int DropAmount; string PickupMessage; float RespawnTime; class GiveQuestType; name IconName; float DropTime; name PickupSound; name UseSound; string StrifeName; // Originally these didn't respawn in deathmatch bool bBigPowerup; // Spawn PickuFlash when picked up. bool bPickupFlash; // Play pickup sound at full volume bool bFullVolPickupSound; // Used by HandlePickup. bool bPickupGood; // Can be displayed in the inventory bar bool bInvBar; // Keep item in inventory even if amount is 0 bool bKeepDepleted; // This item cannot be tossed out bool bUndroppable; // Ignore skill level when giving this item bool bIgnoreSkill; // Automaticly use when picked up. bool bAutoActivate; // For auto activate items always pick up the item, even if it wasn't used. bool bAlwaysPickup; // Keep powerup while travelingbetween levels in a hub bool bHubPower; replication { reliable if (Role == ROLE_Authority && bNetOwner) Amount, MaxAmount; } //========================================================================== // // OnMapSpawn // //========================================================================== void OnMapSpawn(mthing_t* mthing) { if (!mthing) { // Non-placed items are dropped by default. bDropped = true; } if (MaxAmount == DefMaxAmount) { MaxAmount = LineSpecialGameInfo(Level.Game).InvDefaultMaxAmount; } ::OnMapSpawn(mthing); } //========================================================================== // // Destroyed // //========================================================================== void Destroyed() { if (Role == ROLE_Authority) { if (Owner) { EntityEx(Owner).RemoveInventory(self); } Inventory = none; } ::Destroyed(); } //========================================================================== // // Tick // //========================================================================== void Tick(float DeltaTime) { ::Tick(DeltaTime); if (DropTime) { DropTime -= DeltaTime; if (DropTime <= 0.0) { DropTime = 0.0; bSpecial = default.bSpecial; bSolid = default.bSolid; } } } //========================================================================== // // BecomeItem // //========================================================================== final void BecomeItem() { UnlinkFromWorld(); bHidden = true; bNoBlockmap = true; LinkToWorld(); SetState(FindState('Held')); } //========================================================================== // // BecomePickup // //========================================================================== final void BecomePickup() { if (Owner) { EntityEx(Owner).RemoveInventory(self); } UnlinkFromWorld(); bHidden = false; bNoBlockmap = false; LinkToWorld(); SetState(IdleState); } //========================================================================== // // AttachToOwner // //========================================================================== void AttachToOwner(EntityEx NewOwner) { BecomeItem(); NewOwner.AddInventory(self); } //========================================================================== // // DetachedFromOwner // // Event called when item is being removed from Owner's inventory. // //========================================================================== void DetachedFromOwner() { } //========================================================================== // // TouchSpecial // //========================================================================== final void TouchSpecial(EntityEx Toucher) { if (!Toucher.bPickUp) { // Can't be picked up by toucher return; } if (Toucher.Health <= 0) { // Toucher is dead return; } if (!TryPickup(Toucher)) { return; } Toucher.Player.cprint(GetPickupMessage()); PlayPickupSound(Toucher); PlayerEx(Toucher.Player).BonusFlash += BONUSADD; DoPickupSpecial(Toucher); if (bCountItem) { Toucher.Player.ItemCount++; Level.CurrentItems++; } } //========================================================================== // // TryPickup // //========================================================================== bool TryPickup(EntityEx Toucher) { bPickupGood = false; if (Toucher.Inventory && Toucher.Inventory.HandlePickup(self)) { if (!bPickupGood) { return false; } GoAwayAndDie(); } else if (MaxAmount == 0) { // A special case: Items with max amount of 0 can be picked up if // they are autoactivate-able. if (!bAutoActivate) { return false; } // Put it in the inventory long enoung to be used. Toucher.AddInventory(self); bool UseGood = Use(true); Toucher.RemoveInventory(self); if (UseGood || bAlwaysPickup) { GoAwayAndDie(); } else { return false; } } else { Inventory Copy = CreateCopy(Toucher); if (!Copy) { return false; } Copy.AttachToOwner(Toucher); if (bAutoActivate && Copy.Use(true)) { Copy.Amount--; if (Copy.Amount <= 0) { Copy.bSpecial = false; Copy.SetState(Copy.FindState('HoldAndDestroy')); } } } GiveQuest(Toucher); return true; } //========================================================================== // // HandlePickup // // Called for each item in touchers in ventory. Returns true if pickup // should be interrupted. Sets bPickupGood to true if pickup should be // considered successful. // //========================================================================== bool HandlePickup(Inventory Item) { if (Item.Class == Class) { if (Amount < MaxAmount) { Amount += Item.Amount; if (Amount > MaxAmount) { Amount = MaxAmount; } Item.bPickupGood = true; } return true; } if (Inventory) { return Inventory.HandlePickup(Item); } return false; } //========================================================================== // // CreateCopy // //========================================================================== Inventory CreateCopy(EntityEx Toucher) { Inventory Copy; if (GoAway()) { // Must create a copy Copy = Spawn(class(Class)); Copy.Amount = Amount; Copy.MaxAmount = MaxAmount; } else { // Use this one Copy = self; } return Copy; } //========================================================================== // // CreateTossable // // Create item suitable fro dropping. // //========================================================================== Inventory CreateTossable() { if (!IdleState) { // This item has no spawn state so it cannot be seen. return none; } if (bUndroppable || !Owner || Amount <= 0) { return none; } if (Amount == 1 && !bKeepDepleted) { // Drop the current one. BecomePickup(); DropTime = 1.0; bSpecial = false; bSolid = false; return self; } Inventory Copy = Spawn(class(Class)); Copy.Amount = 1; Copy.MaxAmount = MaxAmount; Copy.DropTime = 1.0; Copy.bSpecial = false; Copy.bSolid = false; return Copy; } //========================================================================== // // ShouldStay // // Returns true if item should stay after it's been picked up. // //========================================================================== bool ShouldStay() { return false; } //========================================================================== // // ShouldRespawn // //========================================================================== bool ShouldRespawn() { if (bBigPowerup && !LineSpecialGameInfo(Level.Game).bRespawnBigItems) { return false; } return LineSpecialGameInfo(Level.Game).bRespawnItems; } //========================================================================== // // GoAway // //========================================================================== final bool GoAway() { // Never respawn dropped items. if (bDropped) { if (bPickupFlash) { // Initiate the artifact pickup animation. Spawn(PickupFlash, Origin); } return false; } if (!ShouldStay()) { if (bPickupFlash) { // Initiate the artifact pickup animation. Spawn(PickupFlash, Origin); } if (ShouldRespawn()) { Hide(); } else { // Don't respawn return false; } } return true; } //========================================================================== // // GoAwayAndDie // //========================================================================== final void GoAwayAndDie() { if (!GoAway()) { bSpecial = false; SetState(FindState('HoldAndDestroy')); } } //========================================================================== // // Hide // //========================================================================== final void Hide() { bSpecial = false; bHidden = true; if (LineSpecialGameInfo(Level.Game).bRavenStylePickupRespawn) { SetState(FindState('HideSpecial')); StateTime = 40.0; if (bPickupFlash) { StateTime += 30.0 / 35.0; } } else { SetState(FindState('DormantPickup')); StateTime = 30.0; } if (RespawnTime) { StateTime = RespawnTime; } } //========================================================================== // // GetPickupMessage // //========================================================================== string GetPickupMessage() { return PickupMessage; } //========================================================================== // // DoPickupSpecial // //========================================================================== void DoPickupSpecial(EntityEx Toucher) { if (Special) { Level.ExecuteActionSpecial(Special, Args[0], Args[1], Args[2], Args[3], Args[4], NULL, 0, Toucher); Special = 0; } } //========================================================================== // // PlayPickupSound // //========================================================================== void PlayPickupSound(EntityEx Toucher) { if (PickupSound) { Toucher.PlaySound(PickupSound, CHAN_ITEM, 1.0, bFullVolPickupSound ? ATTN_NONE : ATTN_NORMAL); } } //========================================================================== // // GiveQuest // //========================================================================== final void GiveQuest(EntityEx Toucher) { if (GiveQuestType) { Toucher.GiveInventoryType(GiveQuestType); } } //========================================================================== // // DoRespawn // //========================================================================== bool DoRespawn() { return true; } //========================================================================== // // SpecialDropAction // //========================================================================== bool SpecialDropAction(EntityEx Source) { return false; } //========================================================================== // // PrevInv // // Return previous item with bInvBar flag set. // //========================================================================== Inventory PrevInv() { Inventory Item = Inventory; while (Item && !Item.bInvBar) { Item = Item.Inventory; } return Item; } //========================================================================== // // NextInv // // Return next item with bInvBar flag set. // //========================================================================== Inventory NextInv() { Inventory Ret = none; Inventory Item = EntityEx(Owner).Inventory; while (Item && Item != self) { if (Item.bInvBar) { Ret = Item; } Item = Item.Inventory; } return Ret; } //========================================================================== // // Use // //========================================================================== bool Use(bool Pickup) { return false; } //========================================================================== // // DoEffect // //========================================================================== void DoEffect() { } //========================================================================== // // GetBlend // //========================================================================== int GetBlend() { return 0; } //========================================================================== // // AbsorbDamage // //========================================================================== void AbsorbDamage(int damage, name DmgType, out int NewDamage) { if (Inventory) { Inventory.AbsorbDamage(damage, DmgType, NewDamage); } } //========================================================================== // // OwnerDied // //========================================================================== void OwnerDied() { } //========================================================================== // // GetSpeedFactor // //========================================================================== float GetSpeedFactor() { if (Inventory) { return Inventory.GetSpeedFactor(); } else { return 1.0; } } //========================================================================== // // A_RestoreSpecialThing1 // // Make a special thing visible again. // //========================================================================== final void A_RestoreSpecialThing1() { bHidden = false; if (DoRespawn()) { PlaySound('misc/spawn', CHAN_VOICE); } } //========================================================================== // // A_RestoreSpecialThing2 // //========================================================================== final void A_RestoreSpecialThing2() { bSpecial = true; SetState(IdleState); } states { // Hide pickup like in Doom and Strife. DormantPickup: TNT1 A 1050 TNT1 A -1 { EntityEx A; bHidden = false; bSpecial = true; SetState(IdleState); // spawn a teleport fog at the new spot A = Spawn(ItemFog, Origin); A.PlaySound('misc/spawn', CHAN_ITEM); } Stop // Hide for 40 secs HideSpecial: ACLO E 1400 ACLO A 4 A_RestoreSpecialThing1 ACLO BABCBCDC 4 ACLO D 4 A_RestoreSpecialThing2 Stop // Invisible state for held items Held: TNT1 A -1 Stop // Will destroy item as soon as possible HoldAndDestroy: TNT1 A 1 Stop } defaultproperties { Amount = 1; MaxAmount = 1; bSpecial = true; bNoPassMobj = true; PickupMessage = "You got a pickup"; PickupSound = 'misc/i_pkup'; UseSound = 'misc/invuse'; }