swwmgz_m/zscript/swwm_ammo.zsc
Marisa Kirisame 42db2d3603 Added various screen shaders, plus a bunch of other changes.
Spreadgun rebalancing.
Underwater sounds.
Embiggener use sound.
Other small things here and there.
2020-03-02 14:41:28 +01:00

1049 lines
20 KiB
Text

// All the ammo items go here
// Common code for ammo division
Mixin Class SWWMAmmo
{
private Inventory DoDrop( Class<Inventory> type )
{
let copy = Inventory(Spawn(type,Owner.Pos,NO_REPLACE));
if ( !copy ) return null;
copy.DropTime = 30;
copy.bSpecial = copy.bSolid = false;
copy.SetOrigin(Owner.Vec3Offset(0,0,10.),false);
copy.Angle = Owner.Angle;
copy.VelFromAngle(5.);
copy.Vel.Z = 1.;
copy.Vel += Owner.Vel;
copy.bNoGravity = false;
copy.ClearCounters();
copy.OnDrop(Owner);
copy.vel += (RotateVector((FRandom[Junk](-1.5,.5),FRandom[Junk](-2.5,2.5)),Owner.angle),FRandom[Junk](2.,5.));
return copy;
}
private bool CmpAmmo( Class<Ammo> a, Class<Ammo> b )
{
let amta = GetDefaultByType(a).Amount;
let amtb = GetDefaultByType(b).Amount;
return (amta < amtb);
}
override bool SpecialDropAction( Actor dropper )
{
if ( Amount != default.Amount )
{
// needed for positioning to work
Owner = dropper;
CreateTossable(Amount);
return true;
}
return false;
}
override inventory CreateTossable( int amt )
{
if ( bUndroppable || bUntossable || !Owner || (Amount <= 0) || (amt == 0) )
return null;
// cap
amt = min(amount,amt);
// enumerate all subclasses
Array<Class<Ammo> > ammotypes;
ammotypes.Clear();
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
if ( AllActorClasses[i] is GetParentAmmo() )
ammotypes.Push((Class<Ammo>)(AllActorClasses[i]));
}
// sort from largest to smallest
for ( int i=0; i<ammotypes.Size(); i++ )
{
int j = 1;
while ( j < ammotypes.Size() )
{
int k = j;
while ( (k > 0) && CmpAmmo(ammotypes[k-1],ammotypes[k]) )
{
Class<Ammo> tmp = ammotypes[k];
ammotypes[k] = ammotypes[k-1];
ammotypes[k-1] = tmp;
k--;
}
j++;
}
}
// perform subdivision
Inventory last = null;
while ( amt > 0 )
{
for ( int i=0; i<ammotypes.Size(); i++ )
{
let def = GetDefaultByType(ammotypes[i]);
if ( amt >= def.Amount )
{
last = DoDrop(ammotypes[i]);
amt -= def.Amount;
Amount -= def.Amount;
break;
}
}
}
return last;
}
override bool HandlePickup( Inventory item )
{
// drop excess ammo
if ( (item is 'Ammo') && (Ammo(item).GetParentAmmo() == GetParentAmmo()) )
{
int excess = Amount+item.Amount;
if ( excess > MaxAmount ) excess -= MaxAmount;
if ( excess < item.Amount )
{
// enumerate all subclasses
Array<Class<Ammo> > ammotypes;
ammotypes.Clear();
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
if ( AllActorClasses[i] is GetParentAmmo() )
ammotypes.Push((Class<Ammo>)(AllActorClasses[i]));
}
// sort from largest to smallest
for ( int i=0; i<ammotypes.Size(); i++ )
{
int j = 1;
while ( j < ammotypes.Size() )
{
int k = j;
while ( (k > 0) && CmpAmmo(ammotypes[k-1],ammotypes[k]) )
{
Class<Ammo> tmp = ammotypes[k];
ammotypes[k] = ammotypes[k-1];
ammotypes[k-1] = tmp;
k--;
}
j++;
}
}
// drop spares
Inventory last;
while ( excess > 0 )
{
for ( int i=0; i<ammotypes.Size(); i++ )
{
let def = GetDefaultByType(ammotypes[i]);
if ( excess >= def.Amount )
{
double ang = FRandom[Junk](0,360);
last = DoDrop(ammotypes[i]);
last.SetOrigin(item.pos,false);
last.vel.xy = (cos(ang),sin(ang))*FRandom[Junk](2,5);
excess -= def.Amount;
break;
}
}
}
}
}
return Super.HandlePickup(item);
}
}
// ============================================================================
// Spreadgun / Wallbuster ammo
// ============================================================================
// Common code for grouped shell handling and per-amount pickup messages
Mixin Class SWWMShellAmmo
{
override string PickupMessage()
{
String tagstr = "$T_"..GetParentAmmo().GetClassName();
tagstr.MakeUpper();
if ( Amount > 1 )
{
tagstr = tagstr.."S";
return String.Format("%d %s",Amount,StringTable.Localize(tagstr));
}
return StringTable.Localize(tagstr);
}
override void ModifyDropAmount( int dropamount )
{
Super.ModifyDropAmount(dropamount);
Amount = max(1,Amount+Random[ShellDrop](-2,1));
}
}
Class RedShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_REDSHELLS";
Stamina 500;
Inventory.Amount 1;
Inventory.MaxAmount 48;
Ammo.BackpackAmount 8;
Ammo.DropAmount 4;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class RedShell2 : RedShell
{
Default
{
Inventory.Amount 2;
}
}
Class RedShell4 : RedShell
{
Default
{
Inventory.Amount 4;
}
}
Class RedShell8 : RedShell
{
Default
{
Inventory.Amount 8;
}
}
Class RedShell12 : RedShell
{
Default
{
Inventory.Amount 12;
}
}
Class RedShell16 : RedShell
{
Default
{
Inventory.Amount 16;
}
}
Class GreenShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_GREENSHELLS";
Stamina 600;
Inventory.Amount 1;
Inventory.MaxAmount 40;
Ammo.BackpackAmount 4;
Ammo.DropAmount 3;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class GreenShell2 : GreenShell
{
Default
{
Inventory.Amount 2;
}
}
Class GreenShell4 : GreenShell
{
Default
{
Inventory.Amount 4;
}
}
Class GreenShell8 : GreenShell
{
Default
{
Inventory.Amount 8;
}
}
Class GreenShell12 : GreenShell
{
Default
{
Inventory.Amount 12;
}
}
Class WhiteShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_WHITESHELLS";
Stamina 900;
Inventory.Amount 1;
Inventory.MaxAmount 20;
Ammo.BackpackAmount 2;
Ammo.DropAmount 2;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class WhiteShell2 : WhiteShell
{
Default
{
Inventory.Amount 2;
}
}
Class WhiteShell4 : WhiteShell
{
Default
{
Inventory.Amount 4;
}
}
Class WhiteShell8 : WhiteShell
{
Default
{
Inventory.Amount 8;
}
}
Class BlueShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_BLUESHELLS";
Stamina 700;
Inventory.Amount 1;
Inventory.MaxAmount 24;
Ammo.BackpackAmount 4;
Ammo.DropAmount 3;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class BlueShell2 : BlueShell
{
Default
{
Inventory.Amount 2;
}
}
Class BlueShell4 : BlueShell
{
Default
{
Inventory.Amount 4;
}
}
Class BlueShell8 : BlueShell
{
Default
{
Inventory.Amount 8;
}
}
Class BlackShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_BLACKSHELLS";
Stamina 1000;
Inventory.Amount 1;
Inventory.MaxAmount 12;
Ammo.BackpackAmount 2;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class BlackShell2 : BlackShell
{
Default
{
Inventory.Amount 2;
}
}
Class BlackShell4 : BlackShell
{
Default
{
Inventory.Amount 4;
}
}
Class PurpleShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_PURPLESHELLS";
Stamina 800;
Inventory.Amount 1;
Inventory.MaxAmount 20;
Ammo.BackpackAmount 4;
Ammo.DropAmount 2;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class PurpleShell2 : PurpleShell
{
Default
{
Inventory.Amount 2;
}
}
Class PurpleShell4 : PurpleShell
{
Default
{
Inventory.Amount 4;
}
}
Class GoldShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_GOLDSHELLS";
Stamina 0;
Inventory.Amount 1;
Inventory.MaxAmount 3;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+COUNTITEM;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
// ============================================================================
// Eviscerator ammo
// ============================================================================
Class EvisceratorShell : Ammo
{
Mixin SWWMAmmo;
Default
{
Tag "$T_EVISHELLS";
Inventory.PickupMessage "$T_EVISHELL";
Stamina 2500;
Inventory.Amount 1;
Inventory.MaxAmount 30;
Ammo.BackpackAmount 3;
Ammo.DropAmount 3;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class EvisceratorSixPack : EvisceratorShell
{
Default
{
Inventory.PickupMessage "$I_EVISHELLPAK";
Inventory.Amount 6;
}
}
// ============================================================================
// Hellblazer ammo
// ============================================================================
Class HellblazerMissiles : Ammo
{
Mixin SWWMAmmo;
Default
{
Tag "$T_HELLMISSILES";
Inventory.PickupMessage "$T_HELLMISSILE";
Stamina 6000;
Inventory.Amount 1;
Inventory.MaxAmount 60;
Ammo.BackpackAmount 3;
Ammo.DropAmount 3;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class HellblazerMissileMag : HellblazerMissiles
{
Default
{
Inventory.PickupMessage "$T_HELLMISSILEMAG";
Inventory.Amount 6;
}
}
Class HellblazerCrackshots : Ammo
{
Mixin SWWMAmmo;
Default
{
Tag "$T_HELLCLUSTERS";
Inventory.PickupMessage "$T_HELLCLUSTER";
Stamina 8000;
Inventory.Amount 1;
Inventory.MaxAmount 24;
Ammo.BackpackAmount 2;
Ammo.DropAmount 2;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class HellblazerCrackshotMag : HellblazerCrackshots
{
Default
{
Inventory.PickupMessage "$T_HELLCLUSTERMAG";
Inventory.Amount 3;
}
}
Class HellblazerRavagers : Ammo
{
Mixin SWWMAmmo;
Default
{
Tag "$T_HELLBURNINATORS";
Inventory.PickupMessage "$T_HELLBURNINATOR";
Stamina 12000;
Inventory.Amount 1;
Inventory.MaxAmount 9;
Ammo.BackpackAmount 1;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class HellblazerRavagerMag : HellblazerRavagers
{
Default
{
Inventory.PickupMessage "$T_HELLBURNINATORMAG";
Inventory.Amount 3;
}
}
Class HellblazerWarheads : Ammo
{
Mixin SWWMAmmo;
Default
{
Tag "$T_HELLNUKES";
Inventory.PickupMessage "$T_HELLNUKE";
Stamina 25000;
Inventory.Amount 1;
Inventory.MaxAmount 4;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class HellblazerWarheadMag : HellblazerWarheads
{
Default
{
Inventory.PickupMessage "$T_HELLNUKEMAG";
Inventory.Amount 2;
}
}
// ============================================================================
// Sparkster ammo
// ============================================================================
Class SparkUnit : Ammo
{
Default
{
Tag "$T_SPARKUNIT";
Inventory.PickupMessage "$T_SPARKUNIT";
Stamina 20000;
Inventory.Amount 1;
Inventory.MaxAmount 8;
Ammo.BackpackAmount 1;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
// ============================================================================
// Silver Bullet ammo
// ============================================================================
Class SilverBulletAmmo : Ammo
{
Default
{
Tag "$T_XSBMAG";
Inventory.PickupMessage "$T_XSBMAG";
Stamina 6000;
Inventory.Amount 1;
Inventory.MaxAmount 5;
Ammo.BackpackAmount 1;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
// ============================================================================
// Candygun ammo
// ============================================================================
Class CandyGunAmmo : Ammo
{
Default
{
Tag "$T_CANDYMAG";
Inventory.PickupMessage "$T_CANDYMAG";
Stamina 80000;
Inventory.Amount 1;
Inventory.MaxAmount 4;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class CandyGunSpares : Ammo
{
Default
{
Tag "$T_CANDYSPARE";
Stamina 600000;
Inventory.Amount 1;
Inventory.MaxAmount 4;
Ammo.BackpackMaxAmount 4;
}
}
// ============================================================================
// Ynykron ammo
// ============================================================================
Class YnykronAmmo : Ammo
{
Default
{
Tag "$T_YNYKRONAMMO";
Inventory.PickupMessage "$T_YNYKRONAMMO";
Stamina 400000;
Inventory.Amount 1;
Inventory.MaxAmount 1;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
// ============================================================================
// Ammo fabricator
// ============================================================================
Class AmmoFabricator : Inventory abstract
{
int budget, pertype, maxunitprice;
Property Budget : budget;
Property PerType : pertype;
Property MaxUnitPrice : maxunitprice;
override Inventory CreateCopy( Actor other )
{
// additional lore
SWWMLoreLibrary.Add(other.player,"Fabricator");
return Super.CreateCopy(other);
}
bool FabricateAmmo()
{
Array<Class<Ammo> > available;
// populate ammo production list
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let a = (Class<Ammo>)(AllActorClasses[i]);
// only direct descendants of ammo with a set price below our max unit price
if ( !a || (a.GetParentClass() != 'Ammo') ) continue;
let def = GetDefaultByType(a);
if ( !(def.Stamina) || (def.Stamina > maxunitprice) ) continue;
available.Push(a);
}
// start from lowest to highest needed until we fill the inventory or run out of budget
bool given = false;
int consumed = 0;
String fabstr = "";
bool comma = false;
for ( int i=0; i<available.Size(); i++ )
{
int amt, lim;
int cnt = 0;
Ammo cur = Ammo(Owner.FindInventory(available[i]));
if ( cur )
{
amt = cur.Amount;
lim = cur.MaxAmount;
}
else
{
cur = Ammo(Spawn(available[i]));
amt = cur.Amount = 0;
lim = cur.MaxAmount;
cur.AttachToOwner(Owner);
}
while ( (amt < lim) && (consumed+cur.default.Stamina < budget) && (cnt < pertype) )
{
consumed += cur.default.Stamina;
amt = ++cur.Amount;
cnt++;
given = true;
}
if ( cnt > 0 )
{
if ( comma ) fabstr.AppendFormat(", %dx %s",cnt,cur.GetTag());
else fabstr.AppendFormat("%dx %s",cnt,cur.GetTag());
comma = true;
}
}
if ( given ) PrintPickupMessage(true,fabstr);
return given;
}
override bool Use( bool pickup )
{
bool shouldautouse = false;
if ( swwm_enforceautouseammo == 1 ) shouldautouse = true;
else if ( swwm_enforceautouseammo == -1 ) shouldautouse = false;
else shouldautouse = CVar.GetCVar('swwm_autouseammo',Owner.player).GetBool();
if ( pickup && !shouldautouse ) return false;
if ( FabricateAmmo() )
{
Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
return true;
}
return false;
}
Default
{
+INVENTORY.INVBAR;
+INVENTORY.AUTOACTIVATE;
+FLOATBOB;
Inventory.UseSound "fabricator/use";
Inventory.MaxAmount 32;
Inventory.InterHubAmount 32;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class FabricatorTier1 : AmmoFabricator
{
Default
{
Tag "$T_FABRICATOR1";
Inventory.Icon "graphics/HUD/Icons/I_Fabricator1.png";
Inventory.PickupMessage "$T_FABRICATOR1";
Inventory.MaxAmount 30;
AmmoFabricator.Budget 5000;
AmmoFabricator.PerType 2;
AmmoFabricator.MaxUnitPrice 2500;
Stamina 3000;
}
}
Class FabricatorTier2 : AmmoFabricator
{
Default
{
Tag "$T_FABRICATOR2";
Inventory.Icon "graphics/HUD/Icons/I_Fabricator2.png";
Inventory.PickupMessage "$T_FABRICATOR2";
Inventory.MaxAmount 20;
AmmoFabricator.Budget 15000;
AmmoFabricator.PerType 4;
AmmoFabricator.MaxUnitPrice 10000;
Stamina 12000;
}
}
Class FabricatorTier3 : AmmoFabricator
{
Default
{
Tag "$T_FABRICATOR3";
Inventory.Icon "graphics/HUD/Icons/I_Fabricator3.png";
Inventory.PickupMessage "$T_FABRICATOR3";
Inventory.MaxAmount 10;
AmmoFabricator.Budget 120000;
AmmoFabricator.PerType 8;
AmmoFabricator.MaxUnitPrice 80000;
Stamina 150000;
}
}
Class FabricatorTier4 : AmmoFabricator
{
Default
{
Tag "$T_FABRICATOR4";
Inventory.Icon "graphics/HUD/Icons/I_Fabricator4.png";
Inventory.PickupMessage "$T_FABRICATOR4";
Inventory.MaxAmount 5;
AmmoFabricator.Budget int.max;
AmmoFabricator.PerType int.max;
-INVENTORY.AUTOACTIVATE;
Stamina 1920000;
}
}
// ============================================================================
// Hammerspace embiggener
// ============================================================================
Class HammerspaceEmbiggener : Inventory
{
override Inventory CreateCopy( Actor other )
{
other.A_StartSound("powerup/embiggener",CHAN_ITEMEXTRA);
// Find every unique type of ammoitem. Give it to the player if
// he doesn't have it already, and increase its maximum capacity.
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let type = (class<Ammo>)(AllActorClasses[i]);
if ( !type || (type.GetParentClass() != 'Ammo') ) continue;
// check that it's for a valid weapon
bool isvalid = false;
for ( int j=0; j<AllActorClasses.Size(); j++ )
{
let type2 = (class<Weapon>)(AllActorClasses[j]);
if ( !type2 ) continue;
let rep = GetReplacement(type2);
if ( (rep != type2) && !(rep is "DehackedPickup") ) continue;
readonly<Weapon> weap = GetDefaultByType(type2);
if ( !other.player || !other.player.weapons.LocateWeapon(type2) || weap.bCheatNotWeapon ) continue;
if ( (type2 is 'SWWMWeapon') && SWWMWeapon(weap).UsesAmmo(type) )
{
isvalid = true;
break;
}
if ( (weap.AmmoType1 == type) || (weap.AmmoType2 == type) )
{
isvalid = true;
break;
}
}
if ( !isvalid ) continue;
let ammoitem = Ammo(other.FindInventory(type));
int amount = GetDefaultByType(type).BackpackAmount;
// extra ammo in baby mode and nightmare mode
if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor));
if ( amount < 0 ) amount = 0;
if ( !ammoitem )
{
// The player did not have the ammoitem. Add it.
ammoitem = Ammo(Spawn(type));
ammoitem.Amount = amount;
if ( ammoitem.BackpackMaxAmount != ammoitem.default.MaxAmount )
ammoitem.MaxAmount = int(ammoitem.default.MaxAmount*(1+self.Amount/2.));
if ( (ammoitem.Amount > ammoitem.MaxAmount) && !sv_unlimited_pickup )
ammoitem.Amount = ammoitem.MaxAmount;
ammoitem.AttachToOwner(other);
}
else
{
// The player had the ammoitem. Give some more.
if ( ammoitem.BackpackMaxAmount != ammoitem.default.MaxAmount )
ammoitem.MaxAmount = int(ammoitem.default.MaxAmount*(1+self.Amount/2.));
if ( ammoitem.Amount < ammoitem.MaxAmount )
{
ammoitem.Amount += amount;
if ( (ammoitem.Amount > ammoitem.MaxAmount) && !sv_unlimited_pickup )
ammoitem.Amount = ammoitem.MaxAmount;
}
}
}
return Inventory.CreateCopy(other);
}
override bool HandlePickup( Inventory item )
{
bool res = Super.HandlePickup(item);
if ( item.GetClass() == GetClass() )
{
Owner.A_StartSound("powerup/embiggener",CHAN_ITEMEXTRA);
// readjust ammo values to new capacity
for ( Inventory i=Owner.Inv; i; i=i.Inv )
{
if ( !(i is 'Ammo') ) continue;
if ( Ammo(i).BackpackMaxAmount != i.default.MaxAmount )
i.MaxAmount = int(i.Default.MaxAmount*(1+self.Amount/2.));
int amount = Ammo(i).BackpackAmount;
if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor));
i.Amount += amount;
if ( (i.Amount > i.MaxAmount) && !sv_unlimited_pickup )
i.Amount = i.MaxAmount;
}
}
return res;
}
override void DetachFromOwner()
{
// reset upgrade
for ( Inventory i=Owner.Inv; i; i=i.Inv )
{
if ( !(i is 'Ammo') ) continue;
i.MaxAmount = i.Default.MaxAmount;
if ( i.Amount > i.MaxAmount )
i.Amount = i.MaxAmount;
}
}
Default
{
Tag "$T_EMBIGGENER";
Inventory.PickupMessage "$T_EMBIGGENER";
Inventory.MaxAmount 8;
Inventory.InterHubAmount 8;
+INVENTORY.UNDROPPABLE;
+INVENTORY.UNTOSSABLE;
+INVENTORY.UNCLEARABLE;
+INVENTORY.ALWAYSPICKUP;
+COUNTITEM;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}