A whole lot of stuff, whew:

- All ammo pickups done.
 - All weapons basic properties and spawn state set.
 - Implement Hammerspace Embiggener.
 - Corrections to lore stuff and other info.
 - Separated Hellblazer ammo between mags and single units.
 - Fix fourth healthbar being the same color as third.
 - Added "abstract" to some classes, just for safety.
 - Dashing and ramming tweaks.
 - Dashing no longer cancels when getting hurt.
 - Tiny menu fixes.
This commit is contained in:
Mari the Deer 2020-01-30 22:58:10 +01:00
commit 72c4a81ff0
47 changed files with 2151 additions and 210 deletions

View file

@ -1,5 +1,142 @@
// 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.MaxAmount = MaxAmount;
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 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 -= 16;
break;
}
}
}
}
}
return Super.HandlePickup(item);
}
}
// ============================================================================
// Spreadgun / Wallbuster ammo
// ============================================================================
@ -9,7 +146,7 @@ Mixin Class SWWMShellAmmo
{
override string PickupMessage()
{
String tagstr = "$"..GetParentAmmo().GetClassName();
String tagstr = "$T_"..GetParentAmmo().GetClassName();
tagstr.MakeUpper();
if ( Amount > 1 )
{
@ -18,40 +155,29 @@ Mixin Class SWWMShellAmmo
}
return StringTable.Localize(tagstr);
}
override bool HandlePickup( Inventory item )
{
// drop unwanted shells
if ( (item is 'Ammo') && (Ammo(item).GetParentAmmo() == GetParentAmmo()) )
{
int excess = Amount+item.Amount;
if ( excess > MaxAmount ) excess -= MaxAmount;
if ( excess < item.Amount )
{
// drop spares
for ( int i=0; i<excess; i++ )
{
let s = Spawn(GetParentAmmo(),item.pos);
double ang = FRandom[SpareShells](0,360);
s.vel.xy = (cos(ang),sin(ang))*FRandom[SpareShells](1.,3.);
s.vel.z = FRandom[SpareShells](2,5);
}
}
}
return Super.HandlePickup(item);
}
}
Class RedShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_REDSHELLS";
Stamina 500;
Inventory.Amount 1;
Inventory.MaxAmount 60;
Ammo.BackpackAmount 6;
Inventory.MaxAmount 48;
Ammo.BackpackAmount 8;
Ammo.DropAmount 4;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class RedShell2 : RedShell
@ -68,13 +194,6 @@ Class RedShell4 : RedShell
Inventory.Amount 4;
}
}
Class RedShell6 : RedShell
{
Default
{
Inventory.Amount 6;
}
}
Class RedShell8 : RedShell
{
Default
@ -89,17 +208,35 @@ Class RedShell12 : RedShell
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 48;
Inventory.MaxAmount 40;
Ammo.BackpackAmount 4;
Ammo.DropAmount 4;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class GreenShell2 : GreenShell
@ -116,31 +253,42 @@ Class GreenShell4 : GreenShell
Inventory.Amount 4;
}
}
Class GreenShell6 : GreenShell
{
Default
{
Inventory.Amount 6;
}
}
Class GreenShell8 : GreenShell
{
Default
{
Inventory.Amount 6;
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 24;
Inventory.MaxAmount 20;
Ammo.BackpackAmount 2;
Ammo.DropAmount 4;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class WhiteShell2 : WhiteShell
@ -157,24 +305,35 @@ Class WhiteShell4 : WhiteShell
Inventory.Amount 4;
}
}
Class WhiteShell6 : WhiteShell
Class WhiteShell8 : WhiteShell
{
Default
{
Inventory.Amount 6;
Inventory.Amount 8;
}
}
Class BlueShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_BLUESHELLS";
Stamina 700;
Inventory.Amount 1;
Inventory.MaxAmount 30;
Ammo.BackpackAmount 3;
Inventory.MaxAmount 24;
Ammo.BackpackAmount 4;
Ammo.DropAmount 4;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class BlueShell2 : BlueShell
@ -191,24 +350,35 @@ Class BlueShell4 : BlueShell
Inventory.Amount 4;
}
}
Class BlueShell6 : BlueShell
Class BlueShell8 : BlueShell
{
Default
{
Inventory.Amount 6;
Inventory.Amount 8;
}
}
Class BlackShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_BLACKSHELLS";
Stamina 1000;
Inventory.Amount 1;
Inventory.MaxAmount 20;
Inventory.MaxAmount 12;
Ammo.BackpackAmount 2;
Ammo.DropAmount 4;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class BlackShell2 : BlackShell
@ -228,12 +398,25 @@ Class BlackShell4 : BlackShell
Class PurpleShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_PURPLESHELLS";
Stamina 800;
Inventory.Amount 1;
Inventory.MaxAmount 24;
Inventory.MaxAmount 20;
Ammo.BackpackAmount 4;
Ammo.DropAmount 4;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class PurpleShell2 : PurpleShell
@ -250,24 +433,29 @@ Class PurpleShell4 : PurpleShell
Inventory.Amount 4;
}
}
Class PurpleShell6 : PurpleShell
{
Default
{
Inventory.Amount 6;
}
}
Class GoldShell : Ammo
{
Mixin SWWMShellAmmo;
Mixin SWWMAmmo;
Default
{
Tag "$T_GOLDSHELLS";
Stamina 120000;
Inventory.Amount 1;
Inventory.MaxAmount 6;
Inventory.MaxAmount 3;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+COUNTITEM;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
@ -277,12 +465,25 @@ Class GoldShell : Ammo
Class EvisceratorShell : Ammo
{
Mixin SWWMAmmo;
Default
{
Tag "$T_EVISHELLS";
Inventory.PickupMessage "$T_EVISHELL";
Stamina 2500;
Inventory.Amount 1;
Inventory.MaxAmount 60;
Inventory.MaxAmount 30;
Ammo.BackpackAmount 6;
Ammo.DropAmount 6;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
@ -290,6 +491,7 @@ Class EvisceratorSixPack : EvisceratorShell
{
Default
{
Inventory.PickupMessage "$I_EVISHELLPAK";
Inventory.Amount 6;
}
}
@ -300,45 +502,129 @@ Class EvisceratorSixPack : EvisceratorShell
Class HellblazerMissiles : Ammo
{
Mixin SWWMAmmo;
Default
{
Tag "$T_HELLMISSILES";
Inventory.PickupMessage "$T_HELLMISSILE";
Stamina 6000;
Inventory.Amount 1;
Inventory.MaxAmount 12;
Ammo.BackpackAmount 4;
Inventory.MaxAmount 60;
Ammo.BackpackAmount 18;
Ammo.DropAmount 6;
+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 8;
Ammo.BackpackAmount 2;
Inventory.MaxAmount 24;
Ammo.BackpackAmount 6;
Ammo.DropAmount 3;
+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 4;
Ammo.BackpackAmount 1;
Inventory.MaxAmount 9;
Ammo.BackpackAmount 3;
Ammo.DropAmount 3;
+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 2;
Inventory.MaxAmount 4;
Ammo.BackpackAmount 0;
Ammo.DropAmount 2;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class HellblazerWarheadMag : HellblazerWarheads
{
Default
{
Inventory.PickupMessage "$T_HELLNUKEMAG";
Inventory.Amount 2;
}
}
@ -350,10 +636,21 @@ Class SparkUnit : Ammo
{
Default
{
Tag "$T_SPARKUNIT";
Inventory.PickupMessage "$T_SPARKUNIT";
Stamina 20000;
Inventory.Amount 1;
Inventory.MaxAmount 20;
Ammo.BackpackAmount 2;
Inventory.MaxAmount 8;
Ammo.BackpackAmount 1;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
@ -365,10 +662,21 @@ Class SilverBulletAmmo : Ammo
{
Default
{
Tag "$T_XSBMAG";
Inventory.PickupMessage "$T_XSBMAG";
Stamina 6000;
Inventory.Amount 1;
Inventory.MaxAmount 12;
Inventory.MaxAmount 5;
Ammo.BackpackAmount 1;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
@ -384,8 +692,9 @@ Class CandyGunAmmo : Ammo
Inventory.PickupMessage "$T_CANDYMAG";
Stamina 80000;
Inventory.Amount 1;
Inventory.MaxAmount 8;
Inventory.MaxAmount 4;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
}
@ -405,7 +714,7 @@ Class CandyGunSpares : Ammo
Stamina 150000;
Inventory.Amount 1;
Inventory.MaxAmount 4;
Ammo.BackpackAmount 0;
Ammo.BackpackMaxAmount 4;
}
}
@ -417,9 +726,220 @@ Class YnykronAmmo : Ammo
{
Default
{
Tag "$T_YNYKRONAMMO";
Inventory.PickupMessage "$T_YNYKRONAMMO";
Stamina 400000;
Inventory.Amount 1;
Inventory.MaxAmount 2;
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;
Property Budget : budget;
override Inventory CreateCopy( Actor other )
{
// additional lore
SWWMLoreLibrary.Add(other.player,"Fabricator");
SWWMLoreLibrary.Add(other.player,"Cyrus");
return Super.CreateCopy(other);
}
Default
{
+INVENTORY.INVBAR;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class FabricatorTier1 : AmmoFabricator
{
Default
{
Tag "$T_FABRICATOR1";
Inventory.PickupMessage "$T_FABRICATOR1";
Inventory.MaxAmount 30;
AmmoFabricator.Budget 5000;
Stamina 3000;
}
}
Class FabricatorTier2 : AmmoFabricator
{
Default
{
Tag "$T_FABRICATOR2";
Inventory.PickupMessage "$T_FABRICATOR2";
Inventory.MaxAmount 20;
AmmoFabricator.Budget 20000;
Stamina 12000;
}
}
Class FabricatorTier3 : AmmoFabricator
{
Default
{
Tag "$T_FABRICATOR3";
Inventory.PickupMessage "$T_FABRICATOR3";
Inventory.MaxAmount 10;
AmmoFabricator.Budget 500000;
Stamina 480000;
}
}
Class FabricatorTier4 : AmmoFabricator
{
Default
{
Tag "$T_FABRICATOR4";
Inventory.PickupMessage "$T_FABRICATOR4";
Inventory.MaxAmount 5;
AmmoFabricator.Budget -1;
Stamina 1920000;
}
}
// ============================================================================
// Hammerspace embiggener
// ============================================================================
Class HammerspaceEmbiggener : Inventory
{
override Inventory CreateCopy( Actor other )
{
// additional lore
SWWMLoreLibrary.Add(other.player,"Cyrus");
// 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() )
{
// 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;
+FLOATBOB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,8 +3,34 @@
Class Hellblazer : SWWMWeapon
{
int clipcount;
Property ClipCount : clipcount;
override bool UsesAmmo( Class<Ammo> kind )
{
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
for ( int i=0; i<4; i++ ) if ( kind is types[i] ) return true;
return false;
}
Default
{
Tag "$T_HELLBLAZER";
Inventory.PickupMessage "$I_HELLBLAZER";
Obituary "$O_HELLBLAZER";
Weapon.SlotNumber 6;
Weapon.SelectionOrder 1800;
Stamina 40000;
Weapon.AmmoType1 "HellblazerMissiles";
Weapon.AmmoGive1 6;
Hellblazer.ClipCount 6;
+SWWMWEAPON.NOFIRSTGIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -7,8 +7,30 @@ Class WallbusterReloadMenu : GenericMenu
Class Wallbuster : SWWMWeapon
{
Class<Ammo> loaded[25];
bool fired[25];
int rotation[6];
override bool UsesAmmo( Class<Ammo> kind )
{
static const Class<Ammo> types[] = {"RedShell","GreenShell","BlueShell","PurpleShell"};
for ( int i=0; i<4; i++ ) if ( kind is types[i] ) return true;
return false;
}
Default
{
Tag "$T_WALLBUSTER";
Inventory.PickupMessage "$I_WALLBUSTER";
Obituary "$O_WALLBUSTER";
Weapon.SlotNumber 4;
Weapon.SelectionOrder 2200;
Stamina 15000;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -625,6 +625,16 @@ Class SWWMNothing : Actor
}
}
Class SWWMItemFog : Actor
{
States
{
Spawn:
TNT1 A 1;
Stop;
}
}
// Bullet trails from DT
Class WaterHit
{
@ -1041,6 +1051,17 @@ Class SWWMHandler : EventHandler
lastcombat = AddOneliner("fightstart",10);
}
override void WorldThingDied( WorldEvent e )
{
if ( (e.Thing.default.bBOSS && !Random[GoldDrop](0,2)) || (e.Thing.default.bBOSSDEATH && !Random[GoldDrop](0,6)) )
{
let g = Actor.Spawn("GoldShell",e.Thing.Vec3Offset(0,0,e.Thing.Height/2));
double ang = FRandom[SpareShells](0,360);
g.vel.xy = (cos(ang),sin(ang))*FRandom[SpareShells](.4,.8);
g.vel.z = FRandom[SpareShells](2.,4.);
}
}
override void WorldThingDamaged( WorldEvent e )
{
if ( !mutevoice ) mutevoice = CVar.GetCVar('swwm_mutevoice',players[consoleplayer]);
@ -1169,18 +1190,201 @@ Class SWWMHandler : EventHandler
override void CheckReplacement( ReplaceEvent e )
{
if ( (e.Replacee is 'Pistol') || (e.Replacee is 'GoldWand') || (e.Replacee is 'FWeapFist') || (e.Replacee is 'CWeapMace') || (e.Replacee is 'MWeapWand') ) e.Replacement = 'ExplodiumGun';
// shell types (sorted by rarity
static const Class<Actor> redpool[] = {"RedShell","RedShell2","RedShell4","RedShell8","RedShell12","RedShell16"};
static const Class<Actor> greenpool[] = {"GreenShell","GreenShell2","GreenShell4","GreenShell8","GreenShell12"};
static const Class<Actor> whitepool[] = {"WhiteShell","WhiteShell2","WhiteShell4","WhiteShell8"};
static const Class<Actor> purplepool[] = {"PurpleShell","PurpleShell2","PurpleShell4"};
static const Class<Actor> bluepool[] = {"BlueShell","BlueShell2","BlueShell4","BlueShell8"};
static const Class<Actor> blackpool[] = {"BlackShell","BlackShell2","BlackShell4"};
if ( (e.Replacee is 'ItemFog') ) e.Replacement = 'SWWMItemFog';
else if ( (e.Replacee is 'Chainsaw') || (e.Replacee is 'Gauntlets') || (e.Replacee is 'FWeapAxe') ) e.Replacement = 'PusherWeapon';
else if ( (e.Replacee is 'Fist') || (e.Replacee is 'Staff') ) e.Replacement = 'DeepImpact';
else if ( (e.Replacee is 'Pistol') || (e.Replacee is 'GoldWand') || (e.Replacee is 'FWeapFist') || (e.Replacee is 'CWeapMace') || (e.Replacee is 'MWeapWand') ) e.Replacement = 'ExplodiumGun';
else if ( (e.Replacee is 'Shotgun') || (e.Replacee is 'CWeapStaff') ) e.Replacement = 'Spreadgun';
else if ( (e.Replacee is 'SuperShotgun') || (e.Replacee is 'MWeapFrost') ) e.Replacement = 'Wallbuster';
else if ( e.Replacee is 'Crossbow' )
{
if ( Random[Replacements](0,2) ) e.Replacement = 'Spreadgun';
else e.Replacement = 'Wallbuster';
}
else if ( (e.Replacee is 'Chaingun') || (e.Replacee is 'Blaster') || (e.Replacee is 'FWeapHammer') ) e.Replacement = 'Eviscerator';
else if ( (e.Replacee is 'RocketLauncher') || (e.Replacee is 'PhoenixRod') || (e.Replacee is 'CWeapFlame') ) e.Replacement = 'Hellblazer';
else if ( (e.Replacee is 'PlasmaRifle') || (e.Replacee is 'SkullRod') )
{
if ( Random[Replacements](0,2) ) e.Replacement = 'Sparkster';
else e.Replacement = 'SilverBullet';
}
else if ( e.Replacee is 'MWeapLightning' ) e.Replacement = 'Sparkster';
else if ( e.Replacee is 'FWeaponPiece3' ) e.Replacement = 'SilverBullet';
else if ( (e.Replacee is 'BFG9000') || (e.Replacee is 'Mace') )
{
/*if ( !Random[Replacements](0,2) ) e.Replacement = 'Ynykron';
else */e.Replacement = 'CandyGun';
if ( !Random[Replacements](0,2) ) e.Replacement = 'Ynykron';
else e.Replacement = 'CandyGun';
}
else if ( e.Replacee is 'CWeaponPiece2' ) e.Replacement = 'CandyGun';
else if ( e.Replacee is 'MWeaponPiece1' ) e.Replacement = 'Ynykron';
else if ( (e.Replacee == 'Clip') || (e.Replacee == 'GoldWandAmmo') || (e.Replacee == 'GoldWandHefty') || (e.Replacee is 'ArtiPoisonBag') )
{
switch( Random[Replacement](0,6) )
{
case 0:
case 1:
case 2:
e.Replacement = redpool[Random[Replacement](0,2)];
break;
case 3:
case 4:
e.Replacement = greenpool[Random[Replacement](0,2)];
break;
case 5:
e.Replacement = whitepool[Random[Replacement](0,1)];
break;
case 6:
e.Replacement = purplepool[0];
break;
}
}
else if ( (e.Replacee == 'Shell') || (e.Replacee is 'CrossbowAmmo') )
{
switch( Random[Replacement](0,10) )
{
case 0:
case 1:
case 2:
e.Replacement = redpool[Random[Replacement](2,3)];
break;
case 3:
case 4:
e.Replacement = greenpool[Random[Replacement](2,3)];
break;
case 5:
case 6:
e.Replacement = whitepool[Random[Replacement](1,2)];
break;
case 7:
case 8:
e.Replacement = purplepool[Random[Replacement](0,2)];
break;
case 9:
e.Replacement = bluepool[Random[Replacement](0,2)];
break;
case 10:
e.Replacement = blackpool[0];
break;
}
}
else if ( (e.Replacee == 'ShellBox') || (e.Replacee is 'CrossbowHefty') )
{
switch( Random[Replacement](0,14) )
{
case 0:
case 1:
case 2:
case 3:
e.Replacement = redpool[Random[Replacement](3,5)];
break;
case 4:
case 5:
case 6:
e.Replacement = greenpool[Random[Replacement](3,4)];
break;
case 7:
case 8:
case 9:
e.Replacement = whitepool[Random[Replacement](2,3)];
break;
case 10:
case 11:
e.Replacement = purplepool[Random[Replacement](1,2)];
break;
case 12:
case 13:
e.Replacement = bluepool[Random[Replacement](2,3)];
break;
case 14:
e.Replacement = blackpool[Random[Replacement](0,2)];
break;
}
}
else if ( e.Replacee == 'ClipBox' )
{
if ( Random[Replacements](0,2) ) e.Replacement = 'EvisceratorShell';
else e.Replacement = 'EvisceratorSixPack';
}
else if ( e.Replacee == 'BlasterAmmo' ) e.Replacement = 'EvisceratorShell';
else if ( e.Replacee == 'BlasterHefty' ) e.Replacement = 'EvisceratorSixPack';
else if ( (e.Replacee == 'RocketAmmo') || (e.Replacee == 'PhoenixRodAmmo') || (e.Replacee == 'MaceAmmo') )
{
switch ( Random[Replacements](0,9) )
{
case 0:
case 1:
case 2:
case 3:
e.Replacement = 'HellblazerMissiles';
break;
case 4:
case 5:
case 6:
e.Replacement = 'HellblazerCrackshots';
break;
case 7:
case 8:
e.Replacement = 'HellblazerRavagers';
break;
case 9:
e.Replacement = 'HellblazerWarheads';
break;
}
}
else if ( (e.Replacee == 'RocketBox') || (e.Replacee == 'PhoenixRodHefty') || (e.Replacee == 'MaceHefty') )
{
switch ( Random[Replacements](0,9) )
{
case 0:
case 1:
case 2:
case 3:
e.Replacement = 'HellblazerMissileMag';
break;
case 4:
case 5:
case 6:
e.Replacement = 'HellblazerCrackshotMag';
break;
case 7:
case 8:
e.Replacement = 'HellblazerRavagerMag';
break;
case 9:
e.Replacement = 'HellblazerWarheadMag';
break;
}
}
else if ( (e.Replacee == 'Cell') || (e.Replacee == 'SkullRodAmmo') )
{
if ( Random[Replacements](0,3) ) e.Replacement = 'SparkUnit';
else e.Replacement = 'SilverBulletAmmo';
}
else if ( e.Replacee == 'ArtiTeleport' )
{
if ( Random[Replacements](0,2) ) e.Replacement = 'SWWMNothing';
else e.Replacement = 'GoldShell';
}
else if ( e.Replacee is 'MWeaponPiece1' ) e.Replacement = 'CandyGun';
else if ( (e.Replacee == 'CellPack') || (e.Replacee == 'SkullRodHefty') )
{
/*if ( Random[Replacements](0,2) ) e.Replacement = 'SilverBulletAmmo';
else */e.Replacement = 'CandyGunAmmo';
if ( Random[Replacements](0,2) ) e.Replacement = 'SilverBulletAmmo';
else e.Replacement = 'CandyGunAmmo';
}
else if ( e.Replacee == 'Mana1' ) e.Replacement = 'FabricatorTier1';
else if ( e.Replacee == 'Mana2' ) e.Replacement = 'FabricatorTier2';
else if ( e.Replacee == 'Mana3' ) e.Replacement = 'FabricatorTier3';
else if ( e.Replacee == 'ArtiBoostMana' ) e.Replacement = 'FabricatorTier4';
else if ( (e.Replacee == 'Backpack') || (e.Replacee == 'BagOfHolding') || (e.Replacee == 'ArtiPork') ) e.Replacement = 'HammerspaceEmbiggener';
else if ( (e.Replacee == 'FWeaponPiece1') || (e.Replacee == 'FWeaponPiece2')
|| (e.Replacee == 'CWeaponPiece1') || (e.Replacee == 'CWeaponPiece3')
|| (e.Replacee == 'MWeaponPiece2') || (e.Replacee == 'MWeaponPiece3') ) e.Replacement = 'SWWMNothing';
}
override void NetworkProcess( ConsoleEvent e )
@ -1219,9 +1423,11 @@ Class SWWMHandler : EventHandler
Class<Inventory> item = e.Name.Mid(10);
if ( !item ) return;
let def = GetDefaultByType(item);
if ( players[e.Args[1]].mo.GiveInventory(item,1) )
int amt = ((item is 'Ammo')&&Ammo(def).default.DropAmount)?Ammo(def).DropAmount:def.Amount;
int cap = min(amt,players[e.Args[1]].mo.CountInv(item));
if ( players[e.Args[1]].mo.GiveInventory(item,amt) )
{
players[e.Args[0]].mo.TakeInventory(item,1);
players[e.Args[0]].mo.TakeInventory(item,amt);
// add to history
SWWMTradeHistory.RegisterSend(players[e.Args[0]],players[e.Args[1]],def.GetTag());
SWWMTradeHistory.RegisterReceive(players[e.Args[1]],players[e.Args[0]],def.GetTag());
@ -1249,7 +1455,7 @@ Class SWWMHandler : EventHandler
if ( !item ) return;
let i = players[e.Args[0]].mo.FindInventory(item);
if ( !i ) return;
let drop = players[e.Args[0]].mo.DropInventory(i,i.default.Amount);
let drop = players[e.Args[0]].mo.DropInventory(i,((i is 'Ammo')&&Ammo(i).default.DropAmount)?Ammo(i).default.DropAmount:i.default.Amount);
// add some random velocity so multiple drops don't get bunched together
if ( drop ) drop.vel += (Actor.RotateVector((FRandom[Junk](-1.5,.5),FRandom[Junk](-2.5,2.5)),players[e.Args[0]].mo.angle),FRandom[Junk](2.,5.));
}

View file

@ -5,6 +5,19 @@ Class Eviscerator : SWWMWeapon
{
Default
{
Tag "$T_EVISCERATOR";
Inventory.PickupMessage "$I_EVISCERATOR";
Obituary "$O_EVISCERATOR";
Weapon.SlotNumber 5;
Weapon.SelectionOrder 2000;
Stamina 25000;
Weapon.AmmoType1 "EvisceratorShell";
Weapon.AmmoGive1 10;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,8 +3,27 @@
Class Ynykron : SWWMWeapon
{
int clipcount;
Property ClipCount : clipcount;
Default
{
Tag "$T_YNYKRON";
Inventory.PickupMessage "$T_YNYKRON";
Obituary "$O_YNYKRON";
Weapon.SlotNumber 0;
Weapon.SelectionOrder 1000;
Stamina 600000;
Weapon.AmmoType1 "YnykronAmmo";
Weapon.AmmoGive1 1;
+SWWMWEAPON.NOFIRSTGIVE;
Ynykron.ClipCount 1;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,8 +3,41 @@
Class DeepImpact : SWWMWeapon
{
int clipcount;
transient ui TextureID WeaponBox;
transient ui HUDFont mTewiFont;
Property ClipCount : clipcount;
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
// additional lore
SWWMLoreLibrary.Add(other.player,"Locke");
}
override bool ReportHUDAmmo()
{
return true;
}
Default
{
Tag "$T_DEEPIMPACT";
Inventory.PickupMessage "$I_DEEPIMPACT";
Obituary "$O_DEEPIMPACT";
Weapon.UpSound "impact/select";
Weapon.SlotNumber 1;
Weapon.SelectionOrder 3000;
Stamina 2000;
DeepImpact.ClipCount 100;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -190,7 +190,12 @@ Class SWWMStatusBar : BaseStatusBar
bool dummy;
int slot;
if ( inv is 'Weapon' ) [dummy, slot] = CPlayer.weapons.LocateWeapon(Weapon(inv).GetClass());
if ( (slot == (i%10)) && (!Weapon(inv).Ammo1 || (Weapon(inv).Ammo1.Amount > 0)) )
if ( slot != (i%10) ) continue;
// CheckAmmo can't be called from ui, so we have to improvise
// for SWWM weapons I made a function for this at least
if ( (inv is 'SWWMWeapon') && SWWMWeapon(inv).ReportHUDAmmo() )
hasammo = true;
else if ( !(inv is 'SWWMWeapon') && ((!Weapon(inv).Ammo1 || (Weapon(inv).Ammo1.Amount > 0)) || (Weapon(inv).Ammo2 && (Weapon(inv).Ammo2.Amount > 0))) )
hasammo = true;
}
if ( !hasammo ) ncolor = Font.CR_RED;
@ -231,7 +236,7 @@ Class SWWMStatusBar : BaseStatusBar
if ( ht > 500 )
{
hw = int(min(ht-500,500)*0.2);
Screen.DrawTexture(HealthTex[2],false,margin+2,ss.y-(margin+15),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,hw);
Screen.DrawTexture(HealthTex[3],false,margin+2,ss.y-(margin+15),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,hw);
}
int hcolor = Font.CR_RED;
if ( ht > 500 ) hcolor = Font.CR_GOLD;

View file

@ -1,5 +1,5 @@
// Base class for all SWWM Armors
Class SWWMArmor : Armor
Class SWWMArmor : Armor abstract
{
int priority;
@ -57,12 +57,12 @@ Class SWWMArmor : Armor
}
// gives armor when used
Class SWWMSpareArmor : Inventory
Class SWWMSpareArmor : Inventory abstract
{
}
// Base casing classes
Class SWWMCasing : Actor
Class SWWMCasing : Actor abstract
{
int deadtimer, numbounces;
double pitchvel, anglevel;
@ -226,8 +226,27 @@ Class SWWMWeaponLight : DynamicLight
}
// Base class for all SWWM Weapons
Class SWWMWeapon : Weapon
Class SWWMWeapon : Weapon abstract
{
private int SWeaponFlags;
FlagDef NoFirstGive : SWeaponFlags, 0; // don't give ammo on first pickup (for weapons with a clip count)
override void AttachToOwner (Actor other)
{
Inventory.AttachToOwner(other);
Ammo1 = AddAmmo(Owner,AmmoType1,bNoFirstGive?0:AmmoGive1);
Ammo2 = AddAmmo(Owner,AmmoType2,bNoFirstGive?0:AmmoGive2);
SisterWeapon = AddWeapon(SisterWeaponType);
if ( Owner.player )
{
if ( !Owner.player.GetNeverSwitch() && !bNo_Auto_Switch )
Owner.player.PendingWeapon = self;
if ( Owner.player.mo == players[consoleplayer].camera )
StatusBar.ReceivedWeapon(self);
}
GivenAsMorphWeapon = false;
}
override void DetachFromOwner()
{
Owner.A_StopSound(CHAN_WEAPON);
@ -346,6 +365,17 @@ Class SWWMWeapon : Weapon
A_OverlayFlags(PSP_FLASH,PSPF_RENDERSTYLE,true);
A_OverlayRenderStyle(PSP_FLASH,STYLE_Add);
}
// tells the SWWM HUD that this weapon has ammo available
virtual clearscope bool ReportHUDAmmo()
{
return (!Ammo1||(Ammo1.Amount>0)||(Ammo2&&(Ammo2.Amount>0)));
}
// tells the Embiggener that this weapon uses the specified ammo type
// even if it is not its primary one
virtual clearscope bool UsesAmmo( Class<Ammo> kind )
{
return (AmmoType1&&(kind is AmmoType1))||(AmmoType2&&(kind is AmmoType2));
}
Default
{
Weapon.BobStyle "Alpha";

View file

@ -3,8 +3,38 @@
Class PusherWeapon : SWWMWeapon
{
int chargelevel;
transient ui TextureID WeaponBox;
transient ui HUDFont mTewiFont;
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
// additional lore
SWWMLoreLibrary.Add(other.player,"Locke");
}
override bool ReportHUDAmmo()
{
return true;
}
Default
{
Tag "$T_PUSHER";
Inventory.PickupMessage "$I_PUSHER";
Obituary "$O_PUSHER";
Weapon.UpSound "pusher/select";
Weapon.SlotNumber 1;
Weapon.SelectionOrder 2800;
Stamina 5000;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -163,7 +163,9 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
if ( invlist[sel0] is 'Ammo' ) return true;
lastuse = invlist[sel0].GetClass();
lastuseamt = invlist[sel0].Amount;
checkuse = gametic+1;
// don't check weapons
if ( !(invlist[sel0] is 'Weapon') )
checkuse = gametic+1;
EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer);
}
return true;
@ -192,7 +194,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
invlist.Clear();
for ( Inventory inv=players[consoleplayer].mo.Inv; inv; inv=inv.Inv )
{
if ( (inv.Amount <= 0) || !inv.bINVBAR && !(inv is 'Weapon') && !(inv is 'Ammo') ) continue;
if ( (inv.Amount <= 0) || !inv.SpawnState.ValidateSpriteFrame() || (inv is 'Key') || (inv is 'BasicArmor') || (inv is 'HexenArmor') ) continue;
String tag = inv.GetTag();
bool greater = false;
for ( int i=0; i<invlist.Size(); i++ )
@ -434,15 +436,17 @@ Class SWWMKnowledgeBaseMenu : GenericMenu
for ( int i=ofs; i<invlist.Size(); i++ )
{
if ( !invlist[i] ) continue;
if ( invlist[i].MaxAmount > 1 ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
if ( (invlist[i] is 'Ammo') || (invlist[i].MaxAmount > 1) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag());
else str = invlist[i].GetTag();
len = TewiFont.StringWidth(str);
if ( len > longest ) longest = len;
int clscol = (i==sel0)?Font.CR_WHITE:Font.CR_DARKGRAY;
if ( invlist[i] is 'Weapon' ) clscol = (i==sel0)?Font.CR_YELLOW:Font.CR_ORANGE;
else if ( invlist[i] is 'Ammo' ) clscol = (i==sel0)?Font.CR_BROWN:Font.CR_DARKBROWN;
if ( invlist[i] is 'Weapon' ) clscol = (i==sel0)?Font.CR_YELLOW:Font.FindFontColor('DarkYellow');
else if ( invlist[i] is 'Ammo' ) clscol = (i==sel0)?Font.CR_ORANGE:Font.FindFontColor('DarkOrange');
else if ( (invlist[i] is 'Health') || (invlist[i] is 'HealthPickup') ) clscol = (i==sel0)?Font.CR_RED:Font.CR_DARKRED;
else if ( invlist[i] is 'Armor' ) clscol = (i==sel0)?Font.CR_GREEN:Font.CR_DARKGREEN;
else if ( (invlist[i] is 'Armor') || (invlist[i] is 'SWWMSpareArmor') ) clscol = (i==sel0)?Font.CR_GREEN:Font.CR_DARKGREEN;
else if ( invlist[i] is 'PuzzleItem' ) clscol = (i==sel0)?Font.CR_LIGHTBLUE:Font.CR_BLUE;
else if ( invlist[i] is 'PowerupGiver' ) clscol = (i==sel0)?Font.CR_PURPLE:Font.FindFontColor('DarkPurple');
Screen.DrawText(TewiFont,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
yy += 16;
if ( yy >= 369 )

View file

@ -20,6 +20,8 @@ Class Demolitionist : PlayerPawn
int cairtime;
Vector3 oldpos;
int lastmpain;
Default
{
Speed 1;
@ -82,6 +84,11 @@ Class Demolitionist : PlayerPawn
if ( (rep != type2) && !(rep is "DehackedPickup") ) continue;
readonly<Weapon> weap = GetDefaultByType(type2);
if ( !player.weapons.LocateWeapon(type2) || (weap.bCheatNotWeapon && (giveall != ALL_YESYES)) ) continue;
if ( (type2 is 'SWWMWeapon') && SWWMWeapon(weap).UsesAmmo(type) )
{
isvalid = true;
break;
}
if ( (weap.AmmoType1 == type) || (weap.AmmoType2 == type) )
{
isvalid = true;
@ -311,10 +318,12 @@ Class Demolitionist : PlayerPawn
dashsnd = true;
else
{
if ( dashsnd ) A_StartSound("demolitionist/jetstop",CHAN_JETPACK);
if ( dashsnd )
A_StartSound("demolitionist/jetstop",CHAN_JETPACK);
dashsnd = false;
}
if ( dashboost <= 0. ) return;
PainChance = InStateSequence(CurState,FindState("Dash"))?0:255;
if ( InStateSequence(CurState,FindState("Dash")) )
{
Actor a;
@ -325,22 +334,24 @@ Class Demolitionist : PlayerPawn
a.vel = (RotateVector((j,0),angle+i*160),0)-(0,0,1)*j;
a.vel -= vel*.5;
}
Vector3 dir = vel.unit();
double spd = vel.length();
Vector3 dir = vel+dashdir*dashboost;
double spd = dir.length();
dir = dir.unit();
// look for things we could potentially bump into
let bi = BlockThingsIterator.Create(self,200);
bool bumped = false;
while ( bi.Next() )
while ( (spd > 0) && bi.Next() )
{
a = bi.Thing;
if ( !a || (a == self) || !a.bSHOOTABLE || a.bTHRUACTORS ) continue;
Vector3 diff = level.Vec3Diff(level.Vec3Offset(pos,vel),level.Vec3Offset(a.pos,a.vel));
if ( (abs(diff.x) > radius+a.radius) || (abs(diff.y) > radius+a.radius) ) continue;
if ( (diff.z > height) || (diff.z < -a.height) ) continue;
if ( (abs(diff.x) > (radius+a.radius+8)) || (abs(diff.y) > (radius+a.radius+8)) ) continue;
if ( (diff.z > (height+8)) || (diff.z < (8-a.height)) ) continue;
double moveang = atan2(dir.y,dir.x);
Vector3 sc = level.SphericalCoords(pos,a.pos,(moveang,0));
if ( abs(sc.x) > 45 ) continue;
if ( abs(sc.x) > 60 ) continue;
// bosses and large monsters will stop the player
A_QuakeEx(1,1,1,3,0,128,"",QF_RELATIVE|QF_SCALEDOWN);
a.A_StartSound("demolitionist/bump",CHAN_FOOTSTEP,CHANF_OVERLAP);
if ( a.bDONTTHRUST || (a.Mass >= Mass*5) )
{
@ -348,16 +359,16 @@ Class Demolitionist : PlayerPawn
bumped = true;
A_QuakeEx(3,3,3,8,0,128,"",QF_RELATIVE|QF_SCALEDOWN);
A_StartSound("demolitionist/bump",CHAN_FOOTSTEP,CHANF_OVERLAP);
vel -= dir*(5+(spd*30/mass));
vel -= dir*(9+(spd*30/mass));
vel.z += 3+(spd*(20/mass));
}
Vector3 pushdir = Vec3To(a).unit()*0.2+dir*0.8;
Vector3 pushdir = Vec3To(a).unit()*.1+dir*.9;
if ( !a.bDONTTHRUST && (a.Mass < Mass*5) )
{
a.vel += pushdir*(12+(spd*80/max(50,a.mass)));
a.vel += pushdir*(15+(spd*150/max(50,a.mass)));
a.vel.z += 5+(spd*(50/max(50,a.mass)));
}
a.DamageMobj(self,self,int(15+spd*1.5),'Dash',DMG_THRUSTLESS);
a.DamageMobj(self,self,int(15+spd*2.5),'Dash',DMG_THRUSTLESS);
}
}
else if ( InStateSequence(CurState,FindState("Jump")) )
@ -377,7 +388,13 @@ Class Demolitionist : PlayerPawn
// lucky collar
if ( Health < 25 ) damage /= 4;
if ( source == self ) damage /= 2;
return lastdamage = Super.DamageMobj(inflictor,source,damage,mod,flags,angle);
int lastdamage = Super.DamageMobj(inflictor,source,damage,mod,flags,angle);
if ( (lastdamage > 0) && (PainChance == 0) && (level.maptime>lastmpain) )
{
lastmpain = level.maptime;
A_DemoPain();
}
return lastdamage;
}
override void CalcHeight()
{
@ -946,6 +963,7 @@ Class DashTrail : Actor
+NOGRAVITY;
+NOBLOCKMAP;
+DONTSPLASH;
+NOTELEPORT;
}
override void PostBeginPlay()
{
@ -991,6 +1009,7 @@ Class DashTrail2 : Actor
+NOGRAVITY;
+NOBLOCKMAP;
+DONTSPLASH;
+NOTELEPORT;
}
override void PostBeginPlay()
{
@ -1031,6 +1050,7 @@ Class DemolitionistRadiusShockwaveTail : Actor
+NOGRAVITY;
+DONTSPLASH;
+WALLSPRITE;
+NOTELEPORT;
}
States
{
@ -1062,6 +1082,7 @@ Class DemolitionistRadiusShockwave : Actor
+STEPMISSILE;
+NOEXPLODEFLOOR;
+WALLSPRITE;
+NOTELEPORT;
+RIPPER;
}
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
@ -1069,8 +1090,8 @@ Class DemolitionistRadiusShockwave : Actor
if ( damage <= 0 ) return damage;
if ( (target.mass < LARGE_MASS) && !target.bDONTTHRUST )
{
target.vel.xy += vel.xy.unit()*(5000./target.mass)*alpha;
target.vel.z += (800./target.mass)*alpha;
target.vel.xy += vel.xy.unit()*(5000./max(50,target.mass))*alpha;
target.vel.z += (800./max(50,target.mass))*alpha;
}
return damage;
}
@ -1080,6 +1101,7 @@ Class DemolitionistRadiusShockwave : Actor
SDST A 1
{
SetZ(floorz);
Spawn("InvisibleSplasher",Vec3Offset(0,0,2));
let s = Spawn("DemolitionistRadiusShockwaveTail",pos);
s.vel = vel*.8;
s.scale = scale;
@ -1106,6 +1128,7 @@ Class DemolitionistShockwave : Actor
{
+NOGRAVITY;
+NOBLOCKMAP;
+NOTELEPORT;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
}

View file

@ -3,8 +3,62 @@
Class Spreadgun : SWWMWeapon
{
bool loaded;
Class<Ammo> loadammo, nextammo;
transient ui TextureID WeaponBox;
transient ui HUDFont mTewiFont;
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
// additional lore
SWWMLoreLibrary.Add(other.player,"Blackmann");
}
override bool ReportHUDAmmo()
{
static const Class<Ammo> types[] = {"RedShell","GreenShell","WhiteShell","BlueShell","BlackShell","PurpleShell","GoldShell"};
for ( int i=0; i<7; i++ ) if ( Owner.CountInv(types[i]) > 0 ) return true;
return loaded;
}
override bool CheckAmmo( int firemode, bool autoswitch, bool requireammo, int ammocount )
{
static const Class<Ammo> types[] = {"RedShell","GreenShell","WhiteShell","BlueShell","BlackShell","PurpleShell","GoldShell"};
if ( (firemode == PrimaryFire) || (firemode == AltFire) )
{
if ( loaded ) return true;
for ( int i=0; i<7; i++ ) if ( Owner.CountInv(types[i]) > 0 ) return true;
return false;
}
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
}
override bool UsesAmmo( Class<Ammo> kind )
{
static const Class<Ammo> types[] = {"RedShell","GreenShell","WhiteShell","BlueShell","BlackShell","PurpleShell","GoldShell"};
for ( int i=0; i<7; i++ ) if ( kind is types[i] ) return true;
return false;
}
Default
{
Tag "$T_SPREADGUN";
Inventory.PickupMessage "$I_SPREADGUN";
Obituary "$O_SPREADGUN";
Weapon.UpSound "spreadgun/select";
Weapon.SlotNumber 3;
Weapon.SelectionOrder 2400;
Weapon.AmmoType1 "RedShell";
Weapon.AmmoGive1 1;
Stamina 10000;
}
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -3,8 +3,27 @@
Class Sparkster : SWWMWeapon
{
int clipcount;
Property ClipCount : clipcount;
Default
{
Tag "$T_SPARKSTER";
Inventory.PickupMessage "$I_SPARKSTER";
Obituary "$O_SPARKSTER";
Weapon.SlotNumber 7;
Weapon.SelectionOrder 1600;
Stamina 80000;
Weapon.AmmoType1 "SparkUnit";
Weapon.AmmoGive1 1;
Sparkster.ClipCount 8;
+SWWMWEAPON.NOFIRSTGIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}

View file

@ -281,11 +281,11 @@ Class ExplodiumGun : SWWMWeapon
Property ClipCount : ClipCount;
override void AttachToOwner( Actor other )
override Inventory CreateCopy( Actor other )
{
Super.AttachToOwner(other);
// additional lore
SWWMLoreLibrary.Add(other.player,"Munch");
return Super.CreateCopy(other);
}
override void DrawWeapon( double TicFrac, double bx, double by, Vector2 hs, Vector2 ss )
@ -421,6 +421,11 @@ Class ExplodiumGun : SWWMWeapon
c.vel += vel*.5;
}
override bool ReportHUDAmmo()
{
return true;
}
Default
{
Tag "$T_EXPLODIUM";
@ -428,6 +433,7 @@ Class ExplodiumGun : SWWMWeapon
Obituary "$O_EXPLODIUM";
Weapon.UpSound "explodium/select";
Weapon.SlotNumber 2;
Weapon.SelectionOrder 2600;
Stamina 600;
ExplodiumGun.ClipCount 7;
}

View file

@ -145,12 +145,15 @@ Class CandyBeam : Actor
{
Vector3 tdir = level.Vec3Diff(pos,invoker.nextpos);
Vector3 pvel = .1*tdir+(FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](.1,.3);
let m = Spawn(smk,level.Vec3Offset(pos,tdir*.5));
m.vel = pvel;
m.SetShade(Color(1,1,1)*Random[ExploS](64,224));
m.special1 = Random[ExploS](1,3);
m.scale *= 1.5;
m.alpha *= .4;
if ( special2 && !Random[ExploS](0,special2) )
{
let m = Spawn(smk,level.Vec3Offset(pos,tdir*.5));
m.vel = pvel;
m.SetShade(Color(1,1,1)*Random[ExploS](64,224));
m.special1 = Random[ExploS](1,3);
m.scale *= 1.5;
m.alpha *= .4;
}
if ( special1 > ReactionTime )
{
let s = Spawn(pop,invoker.nextpos);
@ -162,6 +165,7 @@ Class CandyBeam : Actor
b.pitch = asin(-invoker.nextdir.z);
b.target = target;
b.special1 = special1+1;
b.special2 = special2;
b.frame = frame;
}
Default
@ -245,6 +249,7 @@ Class CandyPop : Actor
s.target = target;
s.angle = ang;
s.pitch = pt;
s.special2 = 3;
s.ReactionTime += Random[ExploS](-4,12);
}
numpt = Random[ExploS](1,3);
@ -338,7 +343,7 @@ Class CandyMagArm : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
reactiontime = Random[ExploS](6,12);
reactiontime = Random[ExploS](4,7);
double ang, pt;
ang = FRandom[ExploS](0,360);
pt = FRandom[ExploS](-90,90);
@ -351,17 +356,17 @@ Class CandyMagArm : Actor
{
A_CountDown();
Spawn("CandyMagTrail",pos);
SWWMHandler.DoBlast(self,50+3*reactiontime,3000+500*reactiontime);
SWWMHandler.DoBlast(self,50+6*reactiontime,3000+800*reactiontime);
double spd = vel.length();
vel = (vel*.1+(FRandom[ExploS](-.1,.1),FRandom[ExploS](-.1,.1),FRandom[ExploS](-.1,.1))).unit()*spd;
A_Explode(20+reactiontime/2,50+3*reactiontime);
vel = (vel*.1+(FRandom[ExploS](-.7,.7),FRandom[ExploS](-.7,.7),FRandom[ExploS](-.7,.7))).unit()*spd;
A_Explode(20+reactiontime*3,50+6*reactiontime);
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel+vel*.2;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](2,7);
s.scale *= 2.4;
s.alpha *= 0.1+.4*(ReactionTime/12.);
s.alpha *= 0.1+.4*(ReactionTime/8.);
int numpt = Random[ExploS](ReactionTime-12,3);
for ( int i=0; i<numpt; i++ )
{
@ -371,6 +376,7 @@ Class CandyMagArm : Actor
s.target = target;
s.angle = ang;
s.pitch = pt;
s.special2 = 3;
s.ReactionTime += Random[ExploS](8,20);
}
}
@ -417,7 +423,7 @@ Class CandyMagArmBig : CandyMagArm
override void PostBeginPlay()
{
Super.PostBeginPlay();
vel *= 2.;
vel *= 1.4;
}
States
{
@ -426,18 +432,18 @@ Class CandyMagArmBig : CandyMagArm
{
ReactionTime--;
Spawn("CandyMagTrailBig",pos);
SWWMHandler.DoBlast(self,100+3*reactiontime,3000+500*reactiontime);
SWWMHandler.DoBlast(self,100+8*reactiontime,3000+900*reactiontime);
double spd = vel.length();
vel = (vel*.1+(FRandom[ExploS](-.5,.5),FRandom[ExploS](-.5,.5),FRandom[ExploS](-.5,.5))).unit()*spd;
A_Explode(50+reactiontime,100+3*reactiontime);
A_Explode(50+reactiontime*5,100+8*reactiontime);
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel+vel*.2;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](2,7);
s.scale *= 2.4;
s.alpha *= 0.1+.4*(ReactionTime/12.);
int numpt = Random[ExploS](ReactionTime-30,3);
s.alpha *= 0.1+.4*(ReactionTime/6.);
int numpt = Random[ExploS](ReactionTime-15,1);
for ( int i=0; i<numpt; i++ )
{
double ang = FRandom[ExploS](0,360);
@ -446,11 +452,12 @@ Class CandyMagArmBig : CandyMagArm
s.target = target;
s.angle = ang;
s.pitch = pt;
s.special2 = 6;
s.ReactionTime += Random[ExploS](30,60);
}
if ( ReactionTime <= 0 )
{
numpt = Random[ExploS](3,9);
numpt = Random[ExploS](2,6);
for ( int i=0; i<numpt; i++ )
{
double ang = FRandom[ExploS](0,360);
@ -538,7 +545,7 @@ Class CandyGunProj : Actor
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
numpt = int(Random[ExploS](2,3)*(1.+.4*special1));
numpt = int(Random[ExploS](2,4)*(1.+.4*special1));
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("CandyMagArmBig",pos);
@ -565,10 +572,11 @@ Class CandyGunProj : Actor
{
double ang = FRandom[ExploS](0,360);
double pt = FRandom[ExploS](-90,90);
let s = Spawn("CandyBeam",pos);
let s = Spawn((frame>10)?"CandyBeam":"TinyCandyBeam",pos);
s.target = target;
s.angle = ang;
s.pitch = pt;
s.special2 = 1;
s.ReactionTime += Random[ExploS](-12,32)+(25-frame)/2;
}
}
@ -611,8 +619,8 @@ Class CandyMagProj : Actor
A_SetRenderStyle(1.,STYLE_Add);
Scale *= 3.+.2*special1;
A_AlertMonsters();
SWWMHandler.DoBlast(self,200+20*special1,80000+8000*special1);
A_Explode(300+200*special1,200+20*special1);
SWWMHandler.DoBlast(self,250+25*special1,80000+8000*special1);
A_Explode(300+200*special1,250+25*special1);
A_QuakeEx(9,9,9,30,0,500+80*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollintensity:2.);
A_StartSound("candygun/maghit",CHAN_VOICE,attenuation:.24);
A_StartSound("candygun/maghit",CHAN_WEAPON,attenuation:.12);
@ -645,7 +653,7 @@ Class CandyMagProj : Actor
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
numpt = int(Random[ExploS](2,4)*(1.+.4*special1));
numpt = int(Random[ExploS](3,6)*(1.+.4*special1));
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("CandyMagArm",pos);
@ -672,11 +680,12 @@ Class CandyMagProj : Actor
{
double ang = FRandom[ExploS](0,360);
double pt = FRandom[ExploS](-90,90);
let s = Spawn("CandyBeam",pos);
let s = Spawn((frame>15)?"CandyBeam":"TinyCandyBeam",pos);
s.target = target;
s.angle = ang;
s.pitch = pt;
s.ReactionTime += Random[ExploS](-12,12)+(25-frame)/2;
s.special2 = 2;
s.ReactionTime += Random[ExploS](-12,4)+(25-frame)/3;
}
}
Stop;
@ -776,11 +785,11 @@ Class CandyGun : SWWMWeapon
Property ClipCount : ClipCount;
override void AttachToOwner( Actor other )
override Inventory CreateCopy( Actor other )
{
Super.AttachToOwner(other);
// additional lore
SWWMLoreLibrary.Add(other.player,"Munch");
return Super.CreateCopy(other);
}
override void DrawWeapon( double TicFrac, double bx, double by, Vector2 hs, Vector2 ss )
@ -946,22 +955,15 @@ Class CandyGun : SWWMWeapon
override bool CheckAmmo( int fireMode, bool autoSwitch, bool requireAmmo, int ammocount )
{
if ( sv_infiniteammo || Owner.FindInventory('PowerInfiniteAmmo',true) ) return true;
if ( fireMode == PrimaryFire ) return (chambered || (Ammo1.Amount > 0));
if ( fireMode == PrimaryFire ) return (chambered || (clipcount > 0) || (Ammo1.Amount > 0));
if ( fireMode == AltFire ) return (Ammo1.Amount > 0);
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
}
override bool HandlePickup( Inventory item )
override bool ReportHUDAmmo()
{
if ( item.GetClass() == GetClass())
{
if ( Ammo2.Amount < Ammo2.MaxAmount )
Weapon(item).AmmoGive2 = 1;
if ( Weapon(item).PickupForAmmo(self) )
item.bPickupGood = true;
return true;
}
return false;
if ( chambered || (clipcount > 0) ) return true;
return Super.ReportHUDAmmo();
}
Default
@ -971,12 +973,14 @@ Class CandyGun : SWWMWeapon
Obituary "$O_CANDYGUN";
Weapon.UpSound "explodium/select";
Weapon.SlotNumber 9;
Weapon.SelectionOrder 1200;
Stamina 70000;
Weapon.AmmoType1 "CandyGunAmmo";
Weapon.AmmoType2 "CandyGunSpares";
Weapon.AmmoGive1 1;
Weapon.AmmoGive2 0;
Weapon.AmmoGive2 1;
CandyGun.ClipCount 7;
+SWWMWEAPON.NOFIRSTGIVE;
}
States
{
@ -1053,8 +1057,8 @@ Class CandyGun : SWWMWeapon
Reload:
XZW2 A 1
{
if ( invoker.clipcount <= 0 ) return ResolveState("ReloadEmpty");
else if ( (invoker.Ammo1.Amount <= 0) || invoker.clipcount >= invoker.default.clipcount ) return ResolveState("CheckBullet");
if ( (invoker.Ammo1.Amount <= 0) || (invoker.clipcount >= invoker.default.clipcount) ) return ResolveState("CheckBullet");
else if ( invoker.clipcount <= 0 ) return ResolveState("ReloadEmpty");
return ResolveState(null);
}
XZW2 TUVWXYZ 1;

View file

@ -3,8 +3,28 @@
Class SilverBullet : SWWMWeapon
{
bool chambered;
int clipcount;
Property ClipCount : clipcount;
Default
{
Tag "$T_SILVERBULLET";
Inventory.PickupMessage "$T_SILVERBULLET";
Obituary "$O_SILVERBULLET";
Weapon.SlotNumber 8;
Weapon.SelectionOrder 1400;
Stamina 120000;
Weapon.AmmoType1 "SilverBulletAmmo";
Weapon.AmmoGive1 1;
SilverBullet.ClipCount 5;
+SWWMWEAPON.NOFIRSTGIVE;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}