Major code refactoring. SWWMHandler could still use some more, though.
This commit is contained in:
parent
0eec40e723
commit
c5abe83831
94 changed files with 17859 additions and 17678 deletions
501
zscript/items/swwm_ammoextra.zsc
Normal file
501
zscript/items/swwm_ammoextra.zsc
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
// ============================================================================
|
||||
// Ammo fabricator
|
||||
// ============================================================================
|
||||
|
||||
Class AmmoFabricator : Inventory abstract
|
||||
{
|
||||
Mixin SWWMOverlapPickupSound;
|
||||
Mixin SWWMUseToPickup;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private bool CmpFabAmmo( Class<Ammo> a, Class<Ammo> b )
|
||||
{
|
||||
let ia = Owner.FindInventory(a);
|
||||
int cnta = ia?ia.Amount:0;
|
||||
int maxa = ia?ia.MaxAmount:GetDefaultByType(a).Amount;
|
||||
let ib = Owner.FindInventory(b);
|
||||
int cntb = ib?ib.Amount:0;
|
||||
int maxb = ib?ib.MaxAmount:GetDefaultByType(b).Amount;
|
||||
double facta = cnta/double(maxa);
|
||||
double factb = cntb/double(maxb);
|
||||
return (facta >= factb);
|
||||
}
|
||||
|
||||
private int partition_fabammo( Array<Class<Ammo> > a, int l, int h )
|
||||
{
|
||||
Class<Ammo> pv = a[h];
|
||||
int i = (l-1);
|
||||
for ( int j=l; j<=(h-1); j++ )
|
||||
{
|
||||
if ( CmpFabAmmo(pv,a[j]) )
|
||||
{
|
||||
i++;
|
||||
Class<Ammo> tmp = a[j];
|
||||
a[j] = a[i];
|
||||
a[i] = tmp;
|
||||
}
|
||||
}
|
||||
Class<Ammo> tmp = a[h];
|
||||
a[h] = a[i+1];
|
||||
a[i+1] = tmp;
|
||||
return i+1;
|
||||
}
|
||||
private void qsort_fabammo( Array<Class<Ammo> > a, int l, int h )
|
||||
{
|
||||
if ( l >= h ) return;
|
||||
int p = partition_fabammo(a,l,h);
|
||||
qsort_fabammo(a,l,p-1);
|
||||
qsort_fabammo(a,p+1,h);
|
||||
}
|
||||
|
||||
bool FabricateAmmo()
|
||||
{
|
||||
Array<Class<Ammo> > available;
|
||||
// populate ammo production list
|
||||
for ( int i=0; i<AllActorClasses.Size(); i++ )
|
||||
{
|
||||
let a = (Class<Ammo>)(AllActorClasses[i]);
|
||||
// skip over candy gun spares, they're "special ammo"
|
||||
if ( a == 'CandyGunSpares' ) continue;
|
||||
// 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 <= 0) || (def.Stamina > maxunitprice) ) continue;
|
||||
// only ammo for weapons that are valid (can be used)
|
||||
bool isvalid = false;
|
||||
for ( int j=0; j<AllActorClasses.Size(); j++ )
|
||||
{
|
||||
let type = (class<Weapon>)(AllActorClasses[j]);
|
||||
if ( !type ) continue;
|
||||
let rep = GetReplacement(type);
|
||||
if ( (rep != type) && !(rep is "DehackedPickup") ) continue;
|
||||
readonly<Weapon> weap = GetDefaultByType(type);
|
||||
if ( !Owner.player || !Owner.player.weapons.LocateWeapon(type) || weap.bCheatNotWeapon ) continue;
|
||||
let ready = weap.FindState("Ready");
|
||||
if ( !ready || !ready.ValidateSpriteFrame() ) continue;
|
||||
if ( (type is 'SWWMWeapon') && SWWMWeapon(weap).UsesAmmo(a) )
|
||||
{
|
||||
isvalid = true;
|
||||
break;
|
||||
}
|
||||
if ( (weap.AmmoType1 == a) || (weap.AmmoType2 == a) )
|
||||
{
|
||||
isvalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !isvalid ) continue;
|
||||
available.Push(a);
|
||||
}
|
||||
// sort by "need weight" (prioritize ammo that the player lacks over ammo that the player has plenty of
|
||||
qsort_fabammo(available,0,available.Size()-1);
|
||||
// loop through until we fill the inventory or run out of budget
|
||||
bool given = false;
|
||||
int consumed = 0;
|
||||
String fabstr = "";
|
||||
bool comma = false;
|
||||
int tpertype = pertype;
|
||||
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);
|
||||
}
|
||||
// percentage based on DEFAULT max amount (capped at 1 minimum)
|
||||
if ( pertype < 0 ) tpertype = max(1,-int(cur.default.MaxAmount*pertype*.01));
|
||||
while ( (amt < lim) && (consumed+cur.default.Stamina < budget) && (cnt < tpertype) )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
+INVENTORY.INVBAR;
|
||||
+INVENTORY.AUTOACTIVATE;
|
||||
+FLOATBOB;
|
||||
Inventory.UseSound "fabricator/use";
|
||||
Inventory.PickupFlash "SWWMPickupFlash";
|
||||
FloatBobStrength 0.25;
|
||||
Radius 10;
|
||||
Height 24;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
|
||||
Class FabricatorTier1 : AmmoFabricator
|
||||
{
|
||||
Mixin SWWMAutoUseFix;
|
||||
|
||||
Default
|
||||
{
|
||||
Tag "$T_FABRICATOR1";
|
||||
Stamina -2500;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_Fabricator1.png";
|
||||
Inventory.PickupMessage "$T_FABRICATOR1";
|
||||
Inventory.MaxAmount 20;
|
||||
Inventory.InterHubAmount 20;
|
||||
AmmoFabricator.Budget 3000;
|
||||
AmmoFabricator.PerType 1;
|
||||
AmmoFabricator.MaxUnitPrice 2500;
|
||||
}
|
||||
}
|
||||
Class FabricatorTier2 : AmmoFabricator
|
||||
{
|
||||
Mixin SWWMAutoUseFix;
|
||||
|
||||
Default
|
||||
{
|
||||
Tag "$T_FABRICATOR2";
|
||||
Stamina -12000;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_Fabricator2.png";
|
||||
Inventory.PickupMessage "$T_FABRICATOR2";
|
||||
Inventory.MaxAmount 15;
|
||||
Inventory.InterHubAmount 15;
|
||||
AmmoFabricator.Budget 15000;
|
||||
AmmoFabricator.PerType 2;
|
||||
AmmoFabricator.MaxUnitPrice 12000;
|
||||
}
|
||||
}
|
||||
Class FabricatorTier3 : AmmoFabricator
|
||||
{
|
||||
Mixin SWWMAutoUseFix;
|
||||
|
||||
Default
|
||||
{
|
||||
Tag "$T_FABRICATOR3";
|
||||
Stamina -80000;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_Fabricator3.png";
|
||||
Inventory.PickupMessage "$T_FABRICATOR3";
|
||||
Inventory.MaxAmount 10;
|
||||
Inventory.InterHubAmount 10;
|
||||
AmmoFabricator.Budget 100000;
|
||||
AmmoFabricator.PerType 4;
|
||||
AmmoFabricator.MaxUnitPrice 80000;
|
||||
}
|
||||
}
|
||||
Class FabricatorTier4 : AmmoFabricator
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_FABRICATOR4";
|
||||
Stamina -1000000;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_Fabricator4.png";
|
||||
Inventory.PickupMessage "$T_FABRICATOR4";
|
||||
Inventory.MaxAmount 5;
|
||||
Inventory.InterHubAmount 5;
|
||||
AmmoFabricator.Budget int.max;
|
||||
AmmoFabricator.PerType -50;
|
||||
AmmoFabricator.MaxUnitPrice 1000000;
|
||||
-INVENTORY.AUTOACTIVATE;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Hammerspace embiggener
|
||||
// ============================================================================
|
||||
|
||||
Class HammerspaceEmbiggener : Inventory
|
||||
{
|
||||
Mixin SWWMOverlapPickupSound;
|
||||
Mixin SWWMUseToPickup;
|
||||
|
||||
override Inventory CreateCopy( Actor other )
|
||||
{
|
||||
bool traded = (GetClass()=='TradedHammerspaceEmbiggener');
|
||||
if ( !traded ) 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;
|
||||
let ready = weap.FindState("Ready");
|
||||
if ( !ready || !ready.ValidateSpriteFrame() ) 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*self.Amount;
|
||||
if ( traded ) amount = 0;
|
||||
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 > 0 )
|
||||
{
|
||||
double factor = (ammoitem.BackpackMaxAmount-ammoitem.default.MaxAmount)/double(MaxAmount);
|
||||
ammoitem.MaxAmount = int(ammoitem.default.MaxAmount+min(self.Amount,MaxAmount)*factor);
|
||||
}
|
||||
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 > 0 )
|
||||
{
|
||||
double factor = (ammoitem.BackpackMaxAmount-ammoitem.default.MaxAmount)/double(MaxAmount);
|
||||
ammoitem.MaxAmount = int(ammoitem.default.MaxAmount+min(self.Amount,MaxAmount)*factor);
|
||||
}
|
||||
if ( ammoitem.Amount < ammoitem.MaxAmount )
|
||||
{
|
||||
if ( (ammoitem.Amount > 0) && (ammoitem.Amount+amount < 0) )
|
||||
ammoitem.Amount = int.max;
|
||||
else ammoitem.Amount += amount;
|
||||
if ( (ammoitem.Amount > ammoitem.MaxAmount) && !sv_unlimited_pickup )
|
||||
ammoitem.Amount = ammoitem.MaxAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.Amount = min(self.Amount,MaxAmount);
|
||||
if ( GetParentClass() == 'HammerspaceEmbiggener' )
|
||||
{
|
||||
if ( !GoAway() ) Destroy();
|
||||
let copy = Inventory(Spawn('HammerspaceEmbiggener'));
|
||||
copy.ClearCounters();
|
||||
copy.Amount = self.Amount;
|
||||
copy.MaxAmount = self.MaxAmount;
|
||||
return copy;
|
||||
}
|
||||
if ( GoAway() )
|
||||
{
|
||||
let copy = Inventory(Spawn(GetClass()));
|
||||
copy.ClearCounters();
|
||||
copy.Amount = self.Amount;
|
||||
copy.MaxAmount = self.MaxAmount;
|
||||
return copy;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
override bool HandlePickup( Inventory item )
|
||||
{
|
||||
if ( (item.GetClass() == GetClass()) || (item.GetParentClass() == 'HammerspaceEmbiggener') )
|
||||
{
|
||||
bool traded = (item.GetClass()=='TradedHammerspaceEmbiggener');
|
||||
if ( !traded ) Owner.A_StartSound("powerup/embiggener",CHAN_ITEMEXTRA);
|
||||
if ( (Amount > 0) && (Amount+item.Amount < 0) )
|
||||
Amount = int.max;
|
||||
else Amount += item.Amount;
|
||||
if ( Amount > MaxAmount ) Amount = MaxAmount;
|
||||
item.bPickupGood = true;
|
||||
// readjust ammo values to new capacity
|
||||
for ( Inventory i=Owner.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( !(i is 'Ammo') ) continue;
|
||||
if ( Ammo(i).BackpackMaxAmount > 0 )
|
||||
{
|
||||
double factor = (Ammo(i).BackpackMaxAmount-i.default.MaxAmount)/double(MaxAmount);
|
||||
i.MaxAmount = int(i.default.MaxAmount+Amount*factor);
|
||||
}
|
||||
int amount = Ammo(i).BackpackAmount*item.Amount;
|
||||
if ( traded ) i.Amount = 0;
|
||||
if ( (i.Amount > 0) && (i.Amount+amount < 0) )
|
||||
i.Amount = int.max;
|
||||
else i.Amount += amount;
|
||||
if ( (i.Amount > i.MaxAmount) && !sv_unlimited_pickup )
|
||||
i.Amount = i.MaxAmount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// new ammo suddenly added? upgrade it (this shouldn't happen unless fucky scripting has been involved)
|
||||
if ( (item is 'Ammo') && !Owner.FindInventory(Ammo(item).GetParentAmmo()) )
|
||||
{
|
||||
if ( Ammo(item).BackpackMaxAmount > 0 )
|
||||
{
|
||||
double factor = (Ammo(item).BackpackMaxAmount-item.default.MaxAmount)/double(MaxAmount);
|
||||
item.MaxAmount = int(item.default.MaxAmount+Amount*factor);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override void DepleteOrDestroy()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
Super.DepleteOrDestroy();
|
||||
}
|
||||
|
||||
// merges overlapping embiggeners into a bulk upgrade
|
||||
void A_MergeEmbiggeners()
|
||||
{
|
||||
let bt = BlockThingsIterator.Create(self,16);
|
||||
int tamount = Amount;
|
||||
while ( bt.Next() )
|
||||
{
|
||||
let t = bt.Thing;
|
||||
if ( !t || (t == self) || !(t is 'HammerspaceEmbiggener') || !(t.spawnpoint ~== spawnpoint) ) continue;
|
||||
tamount += HammerspaceEmbiggener(t).Amount;
|
||||
t.ClearCounters();
|
||||
t.Destroy();
|
||||
}
|
||||
if ( tamount <= 1 ) return;
|
||||
tamount -= tamount%2; // always even numbered
|
||||
if ( GetClass() == 'BulkHammerspaceEmbiggener' )
|
||||
{
|
||||
Amount = min(tamount,MaxAmount);
|
||||
return;
|
||||
}
|
||||
let n = Spawn("BulkHammerspaceEmbiggener",pos);
|
||||
Inventory(n).Amount = min(tamount,MaxAmount);
|
||||
n.spawnpoint = spawnpoint;
|
||||
n.spawnangle = spawnangle;
|
||||
n.angle = angle;
|
||||
n.pitch = pitch;
|
||||
n.roll = roll;
|
||||
n.special = special;
|
||||
for ( int i=0; i<5; i++ ) n.args[i] = args[i];
|
||||
n.special1 = special1;
|
||||
n.special2 = special2;
|
||||
n.spawnflags = spawnflags&~MTF_SECRET;
|
||||
n.HandleSpawnFlags();
|
||||
n.spawnflags = spawnflags;
|
||||
n.bCountSecret = spawnflags&MTF_SECRET;
|
||||
n.ChangeTid(tid);
|
||||
n.vel = vel;
|
||||
n.master = master;
|
||||
n.tracer = tracer;
|
||||
n.target = target;
|
||||
if ( !bDROPPED ) n.bDROPPED = false;
|
||||
ClearCounters();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
Tag "$T_EMBIGGENER";
|
||||
Stamina -800000;
|
||||
Inventory.PickupMessage "$T_EMBIGGENER";
|
||||
Inventory.MaxAmount 8;
|
||||
Inventory.InterHubAmount 8;
|
||||
Inventory.PickupFlash "SWWMPickupFlash";
|
||||
+INVENTORY.UNDROPPABLE;
|
||||
+INVENTORY.UNTOSSABLE;
|
||||
+INVENTORY.ALWAYSPICKUP;
|
||||
+COUNTITEM;
|
||||
+FLOATBOB;
|
||||
FloatBobStrength 0.25;
|
||||
Radius 8;
|
||||
Height 24;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1 NoDelay A_MergeEmbiggeners();
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
|
||||
// used when cheating or trading, this version does not give ammo and is meant
|
||||
// only for GiveInventory, so it shouldn't be spawned in the world
|
||||
Class TradedHammerspaceEmbiggener : HammerspaceEmbiggener {}
|
||||
|
||||
// used to denote "merged" embiggeners, changes color based on amount
|
||||
// green (2+)
|
||||
// blue (4+)
|
||||
// purple (6+)
|
||||
// black (8+)
|
||||
Class BulkHammerspaceEmbiggener : HammerspaceEmbiggener
|
||||
{
|
||||
override string PickupMessage()
|
||||
{
|
||||
return String.Format("%dx %s",Amount,StringTable.Localize("$T_BULKEMBIGGENER"));
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1 NoDelay
|
||||
{
|
||||
A_MergeEmbiggeners();
|
||||
if ( bDestroyed ) return ResolveState(null);
|
||||
if ( Amount > 1 ) return SpawnState+min(4,Amount/2);
|
||||
return ResolveState(null);
|
||||
}
|
||||
XZW1 BCDE -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
1040
zscript/items/swwm_ammoitems.zsc
Normal file
1040
zscript/items/swwm_ammoitems.zsc
Normal file
File diff suppressed because it is too large
Load diff
172
zscript/items/swwm_armor.zsc
Normal file
172
zscript/items/swwm_armor.zsc
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
// All the armor items go here
|
||||
Class ArmorNugget : SWWMArmor
|
||||
{
|
||||
Default
|
||||
{
|
||||
Inventory.Icon "graphics/HUD/Icons/I_ArmorNugget.png";
|
||||
Inventory.Amount 1;
|
||||
Inventory.MaxAmount 200;
|
||||
Inventory.InterHubAmount 200;
|
||||
SWWMArmor.ArmorPriority 1;
|
||||
SWWMArmor.GiverArmor "ArmorNuggetItem";
|
||||
}
|
||||
|
||||
override int HandleDamage( int damage, Name damageType, int flags )
|
||||
{
|
||||
double factor = amount*.01;
|
||||
return int(ceil(damage*factor));
|
||||
}
|
||||
}
|
||||
Class ArmorNuggetItem : SWWMSpareArmor
|
||||
{
|
||||
override Inventory CreateCopy( Actor other )
|
||||
{
|
||||
// additional lore
|
||||
SWWMLoreLibrary.Add(other.player,"Nugget");
|
||||
return Super.CreateCopy(other);
|
||||
}
|
||||
Default
|
||||
{
|
||||
Tag "$T_NUGGETA";
|
||||
Stamina 300;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_ArmorNugget.png";
|
||||
Inventory.PickupMessage "$T_NUGGETA";
|
||||
Inventory.MaxAmount 20;
|
||||
Inventory.InterHubAmount 20;
|
||||
Inventory.UseSound "misc/armor_pkup";
|
||||
SWWMSpareArmor.GiveArmor "ArmorNugget";
|
||||
+INVENTORY.ALWAYSPICKUP;
|
||||
Radius 4;
|
||||
Height 22;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 # -1 NoDelay
|
||||
{
|
||||
frame = Random[Nugget](0,7);
|
||||
}
|
||||
Stop;
|
||||
Dummy:
|
||||
XZW1 ABCDEFGH -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class ArmorNuggetBundleSpawn : Actor
|
||||
{
|
||||
override void PostBeginPlay()
|
||||
{
|
||||
if ( bCOUNTSECRET ) level.total_secrets--;
|
||||
int bnd = Random[Bundle](2,3);
|
||||
for ( int i=0; i<bnd; i++ )
|
||||
{
|
||||
let a = Spawn("ArmorNuggetItem",Vec3Angle(8,i*(360/bnd)));
|
||||
a.special = special;
|
||||
a.angle = i*(360/bnd);
|
||||
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
|
||||
if ( bCOUNTSECRET )
|
||||
{
|
||||
a.bCOUNTSECRET = true;
|
||||
level.total_secrets++;
|
||||
}
|
||||
}
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Class BlastSuit : SWWMArmor
|
||||
{
|
||||
Default
|
||||
{
|
||||
Inventory.Icon "graphics/HUD/Icons/I_BlastSuit.png";
|
||||
Inventory.Amount 150;
|
||||
Inventory.MaxAmount 150;
|
||||
Inventory.InterHubAmount 150;
|
||||
SWWMArmor.ArmorPriority 2;
|
||||
SWWMArmor.DrainMessage "$D_BLASTSUIT";
|
||||
SWWMArmor.GiverArmor "BlastSuitItem";
|
||||
}
|
||||
|
||||
override int HandleDamage( int damage, Name damageType, int flags )
|
||||
{
|
||||
double factor = .3;
|
||||
if ( flags&DMG_EXPLOSION ) factor = 1.-(1.-factor)*.5;
|
||||
return int(ceil(damage*factor));
|
||||
}
|
||||
}
|
||||
Class BlastSuitItem : SWWMSpareArmor
|
||||
{
|
||||
override Inventory CreateCopy( Actor other )
|
||||
{
|
||||
// additional lore
|
||||
SWWMLoreLibrary.Add(other.player,"BlastSuit");
|
||||
return Super.CreateCopy(other);
|
||||
}
|
||||
Default
|
||||
{
|
||||
Tag "$T_BLASTSUIT";
|
||||
Stamina 40000;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_BlastSuit.png";
|
||||
Inventory.PickupMessage "$T_BLASTSUIT";
|
||||
Inventory.UseSound "armor/blastsuit";
|
||||
SWWMSpareArmor.GiveArmor "BlastSuit";
|
||||
Radius 12;
|
||||
Height 30;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
|
||||
Class WarArmor : SWWMArmor
|
||||
{
|
||||
Default
|
||||
{
|
||||
Inventory.Icon "graphics/HUD/Icons/I_WarArmor.png";
|
||||
Inventory.Amount 250;
|
||||
Inventory.MaxAmount 250;
|
||||
Inventory.InterHubAmount 250;
|
||||
SWWMArmor.ArmorPriority 6;
|
||||
SWWMArmor.DrainMessage "$D_WARARMOR";
|
||||
SWWMArmor.GiverArmor "WarArmorItem";
|
||||
}
|
||||
|
||||
override int HandleDamage( int damage, Name damageType, int flags )
|
||||
{
|
||||
double factor;
|
||||
// should be enough "elemental" damage types I guess
|
||||
if ( (damageType == 'Fire') || (damageType == 'Ice') || (damageType == 'Slime') || (damageType == 'Electric') || (damageType == 'Wind') || (damageType == 'Water') || (damageType == 'Corroded') || (damageType == 'Lava') ) factor = .8;
|
||||
else factor = .5;
|
||||
if ( flags&DMG_EXPLOSION ) factor = 1.-(1.-factor)*.7;
|
||||
return int(ceil(damage*factor));
|
||||
}
|
||||
}
|
||||
Class WarArmorItem : SWWMSpareArmor
|
||||
{
|
||||
override Inventory CreateCopy( Actor other )
|
||||
{
|
||||
// additional lore
|
||||
SWWMLoreLibrary.Add(other.player,"WarArmor");
|
||||
return Super.CreateCopy(other);
|
||||
}
|
||||
Default
|
||||
{
|
||||
Tag "$T_WARARMOR";
|
||||
Stamina 100000;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_WarArmor.png";
|
||||
Inventory.PickupMessage "$T_WARARMOR";
|
||||
Inventory.UseSound "armor/wararmor";
|
||||
SWWMSpareArmor.GiveArmor "WarArmor";
|
||||
Radius 16;
|
||||
Height 32;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
377
zscript/items/swwm_baseammo.zsc
Normal file
377
zscript/items/swwm_baseammo.zsc
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
// 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;
|
||||
}
|
||||
|
||||
override bool SpecialDropAction( Actor dropper )
|
||||
{
|
||||
if ( swwm_enemydrops >= 0 )
|
||||
{
|
||||
if ( Amount == default.Amount ) return false;
|
||||
// subdivide
|
||||
Owner = dropper; // needed for positioning to work
|
||||
CreateTossable(Amount);
|
||||
return true;
|
||||
}
|
||||
// no ammo drops from enemies
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CmpAmmo( Class<Ammo> a, Class<Ammo> b )
|
||||
{
|
||||
let amta = GetDefaultByType(a).Amount;
|
||||
let amtb = GetDefaultByType(b).Amount;
|
||||
return (amta < amtb);
|
||||
}
|
||||
|
||||
private int partition_ammotypes( Array<Class<Ammo> > a, int l, int h )
|
||||
{
|
||||
Class<Ammo> pv = a[h];
|
||||
int i = (l-1);
|
||||
for ( int j=l; j<=(h-1); j++ )
|
||||
{
|
||||
if ( CmpAmmo(pv,a[j]) )
|
||||
{
|
||||
i++;
|
||||
Class<Ammo> tmp = a[j];
|
||||
a[j] = a[i];
|
||||
a[i] = tmp;
|
||||
}
|
||||
}
|
||||
Class<Ammo> tmp = a[h];
|
||||
a[h] = a[i+1];
|
||||
a[i+1] = tmp;
|
||||
return i+1;
|
||||
}
|
||||
private void qsort_ammotypes( Array<Class<Ammo> > a, int l, int h )
|
||||
{
|
||||
if ( l >= h ) return;
|
||||
int p = partition_ammotypes(a,l,h);
|
||||
qsort_ammotypes(a,l,p-1);
|
||||
qsort_ammotypes(a,p+1,h);
|
||||
}
|
||||
|
||||
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
|
||||
qsort_ammotypes(ammotypes,0,ammotypes.Size()-1);
|
||||
// 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);
|
||||
}
|
||||
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
// drop excess ammo
|
||||
if ( !sv_infiniteammo && !Owner.FindInventory('PowerInfiniteAmmo') )
|
||||
{
|
||||
int excess = Amount-MaxAmount;
|
||||
if ( excess > 0 ) CreateTossable(excess);
|
||||
}
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
+INVENTORY.IGNORESKILL;
|
||||
Inventory.PickupFlash "SWWMPickupFlash";
|
||||
}
|
||||
}
|
||||
|
||||
// Common code for individual bullets
|
||||
Class MagAmmo : Inventory abstract
|
||||
{
|
||||
Mixin SWWMOverlapPickupSound;
|
||||
Mixin SWWMUseToPickup;
|
||||
|
||||
Class<Ammo> ParentAmmo;
|
||||
Ammo pamo;
|
||||
int ClipSize;
|
||||
int countdown;
|
||||
|
||||
Property ParentAmmo : ParentAmmo;
|
||||
Property ClipSize : ClipSize;
|
||||
|
||||
default
|
||||
{
|
||||
+INVENTORY.KEEPDEPLETED;
|
||||
Inventory.PickupSound "misc/bullet_pkup";
|
||||
Inventory.Amount 1;
|
||||
Inventory.PickupFlash "SWWMPickupFlash";
|
||||
}
|
||||
|
||||
override bool HandlePickup( Inventory item )
|
||||
{
|
||||
// see if the mag can be split apart
|
||||
if ( (item is 'Ammo') && (ParentAmmo == Ammo(item).GetParentAmmo()) )
|
||||
{
|
||||
// double-check that parent ammo exists
|
||||
if ( !pamo )
|
||||
{
|
||||
pamo = Ammo(Owner.FindInventory(ParentAmmo));
|
||||
if ( !pamo )
|
||||
{
|
||||
pamo = Ammo(Spawn(ParentAmmo));
|
||||
pamo.AttachToOwner(Owner);
|
||||
pamo.Amount = 0;
|
||||
}
|
||||
}
|
||||
if ( (pamo.Amount >= pamo.MaxAmount) && (Amount < MaxAmount) )
|
||||
{
|
||||
// split
|
||||
for ( int i=0; i<item.Amount; i++ )
|
||||
{
|
||||
int bul = ClipSize;
|
||||
int maxgiveamt = min(MaxAmount-Amount,bul);
|
||||
int dropamt = bul-maxgiveamt;
|
||||
if ( dropamt > 0 ) CreateTossable(dropamt);
|
||||
Amount = min(MaxAmount,Amount+bul);
|
||||
}
|
||||
item.bPickupGood = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Super.HandlePickup(item);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
override bool SpecialDropAction( Actor dropper )
|
||||
{
|
||||
if ( swwm_enemydrops >= 0 )
|
||||
{
|
||||
if ( Amount == default.Amount ) return false;
|
||||
// subdivide
|
||||
Owner = dropper; // needed for positioning to work
|
||||
CreateTossable(Amount);
|
||||
return true;
|
||||
}
|
||||
// no ammo drops from enemies
|
||||
return true;
|
||||
}
|
||||
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
// drop excess ammo
|
||||
if ( !sv_infiniteammo && !Owner.FindInventory('PowerInfiniteAmmo') )
|
||||
{
|
||||
int excess = Amount-MaxAmount;
|
||||
if ( excess > 0 ) CreateTossable(excess);
|
||||
}
|
||||
if ( !pamo )
|
||||
{
|
||||
pamo = Ammo(Owner.FindInventory(ParentAmmo));
|
||||
if ( !pamo )
|
||||
{
|
||||
pamo = Ammo(Spawn(ParentAmmo));
|
||||
pamo.AttachToOwner(Owner);
|
||||
pamo.Amount = 0;
|
||||
}
|
||||
}
|
||||
// check if we can fill a mag (delayed)
|
||||
if ( (Amount < ClipSize) || (pamo.Amount >= pamo.MaxAmount) )
|
||||
{
|
||||
countdown = 35;
|
||||
return;
|
||||
}
|
||||
if ( countdown-- > 0 ) return;
|
||||
MagFill();
|
||||
}
|
||||
|
||||
bool MagFill()
|
||||
{
|
||||
// double-check that parent ammo exists
|
||||
if ( !pamo )
|
||||
{
|
||||
pamo = Ammo(Owner.FindInventory(ParentAmmo));
|
||||
if ( !pamo )
|
||||
{
|
||||
pamo = Ammo(Spawn(ParentAmmo));
|
||||
pamo.AttachToOwner(Owner);
|
||||
pamo.Amount = 0;
|
||||
}
|
||||
}
|
||||
bool given = false;
|
||||
while ( (pamo.Amount < pamo.MaxAmount) && (Amount >= ClipSize) )
|
||||
{
|
||||
pamo.Amount++;
|
||||
Amount -= ClipSize;
|
||||
given = true;
|
||||
if ( Owner.CheckLocalView() )
|
||||
pamo.PrintPickupMessage(true,pamo.PickupMessage());
|
||||
}
|
||||
if ( given ) pamo.PlayPickupSound(Owner);
|
||||
return given;
|
||||
}
|
||||
|
||||
override inventory CreateTossable( int amt )
|
||||
{
|
||||
if ( bUndroppable || bUntossable || !Owner || (Amount <= 0) || (amt == 0) )
|
||||
return null;
|
||||
// cap
|
||||
amt = min(amount,amt);
|
||||
// perform subdivision
|
||||
Inventory last = null;
|
||||
let pammo = GetDefaultByType(ParentAmmo);
|
||||
while ( amt > 0 )
|
||||
{
|
||||
// drop full mag if possible
|
||||
if ( amt >= ClipSize )
|
||||
{
|
||||
last = DoDrop(ParentAmmo);
|
||||
amt -= ClipSize;
|
||||
Amount -= ClipSize;
|
||||
continue;
|
||||
}
|
||||
// drop individual bullets
|
||||
last = DoDrop(GetClass());
|
||||
amt--;
|
||||
Amount--;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
override void ModifyDropAmount( int dropamount )
|
||||
{
|
||||
Super.ModifyDropAmount(dropamount);
|
||||
Amount = min(Random[ShellDrop](1,ClipSize),Amount);
|
||||
}
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
185
zscript/items/swwm_basearmor.zsc
Normal file
185
zscript/items/swwm_basearmor.zsc
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
// Base class for all SWWM Armors
|
||||
Class SWWMArmor : Armor abstract
|
||||
{
|
||||
int priority;
|
||||
String drainmsg;
|
||||
Class<SWWMSpareArmor> parent;
|
||||
|
||||
Property ArmorPriority : priority;
|
||||
Property DrainMessage : drainmsg;
|
||||
Property GiverArmor : parent;
|
||||
|
||||
Default
|
||||
{
|
||||
+INVENTORY.AUTOACTIVATE;
|
||||
+INVENTORY.UNTOSSABLE;
|
||||
+INVENTORY.UNDROPPABLE;
|
||||
+INVENTORY.KEEPDEPLETED;
|
||||
+INVENTORY.ALWAYSPICKUP;
|
||||
}
|
||||
override void AttachToOwner( Actor other )
|
||||
{
|
||||
Super.AttachToOwner(other);
|
||||
// find last armor that's better than us
|
||||
Inventory found = null;
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( !(i is 'SWWMArmor') || (i == self) || (SWWMArmor(i).priority < priority) ) continue;
|
||||
found = i;
|
||||
}
|
||||
if ( !found )
|
||||
{
|
||||
// find first item with an armor worse than us after it
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( (i == self) || !(i.Inv is 'SWWMArmor') ) continue;
|
||||
if ( SWWMArmor(i.Inv).priority > priority ) continue;
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
{
|
||||
// is first item plating or a collar?
|
||||
if ( (other.Inv is 'AlmasteelPlating') || (other.Inv is 'SayaCollar') )
|
||||
{
|
||||
// we're good
|
||||
return;
|
||||
}
|
||||
// find first item with plating or collar after it
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( (i == self) || (!(i.Inv is 'AlmasteelPlating' ) && !(i.Inv is 'SayaCollar')) ) continue;
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
{
|
||||
// check if first item in inventory is health or a sandwich
|
||||
if ( (other.Inv is 'SWWMHealth') || (other.Inv is 'GrilledCheeseSandwich') )
|
||||
{
|
||||
// we're good
|
||||
return;
|
||||
}
|
||||
// find first item with health or sandwich after it
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( (i == self) || (!(i.Inv is 'SWWMHealth' ) && !(i.Inv is 'GrilledCheeseSandwich')) ) continue;
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
{
|
||||
// find last of either invinciball/ragekit/barrier power
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( !(i is 'InvinciballPower') && !(i is 'RagekitPower') && !(i is 'BarrierPower') ) continue;
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
if ( !found ) return;
|
||||
// place ourselves right after it
|
||||
Inventory saved = found.Inv;
|
||||
found.Inv = self;
|
||||
other.Inv = Inv;
|
||||
Inv = saved;
|
||||
}
|
||||
// for subclasses
|
||||
virtual int HandleDamage( int damage, Name damageType, int flags )
|
||||
{
|
||||
return damage;
|
||||
}
|
||||
override void AbsorbDamage( int damage, Name damageType, out int newdamage, Actor inflictor, Actor source, int flags )
|
||||
{
|
||||
int saved;
|
||||
if ( (amount <= 0) || DamageTypeDefinition.IgnoreArmor(damageType) || (damage <= 0) )
|
||||
return;
|
||||
SWWMHandler.DoFlash(Owner,Color(int(clamp(damage*.15,1,16)),255,224,192),3);
|
||||
Owner.A_StartSound("armor/hit",CHAN_BODY,CHANF_DEFAULT,clamp(damage*.03,0.,1.),2.5);
|
||||
saved = HandleDamage(damage,damageType,flags);
|
||||
int healed = max(0,saved-damage);
|
||||
saved = min(saved,damage);
|
||||
if ( amount <= saved ) saved = amount;
|
||||
newdamage -= saved;
|
||||
if ( healed > 0 ) Owner.GiveBody(healed);
|
||||
if ( (swwm_strictuntouchable == 1) && (saved > 0) && Owner.player )
|
||||
{
|
||||
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
||||
if ( hnd ) hnd.tookdamage[Owner.PlayerNumber()] = true;
|
||||
}
|
||||
amount -= saved;
|
||||
damage = newdamage;
|
||||
bool shouldautouse = false;
|
||||
if ( swwm_enforceautousearmor == 1 ) shouldautouse = true;
|
||||
else if ( swwm_enforceautousearmor == -1 ) shouldautouse = false;
|
||||
else shouldautouse = CVar.GetCVar('swwm_autousearmor',Owner.player).GetBool();
|
||||
if ( (amount <= (MaxAmount-default.Amount)) && (Owner.CountInv(parent) > 0) && shouldautouse )
|
||||
{
|
||||
if ( GetDefaultByType(parent).UseSound ) Owner.A_StartSound(GetDefaultByType(parent).UseSound,CHAN_ITEMEXTRA,CHANF_DEFAULT,.6);
|
||||
int tgive = 0;
|
||||
while ( (amount <= (MaxAmount-default.Amount)) && (Owner.CountInv(parent) > 0) )
|
||||
{
|
||||
if ( swwm_accdamage ) tgive += default.Amount;
|
||||
else SWWMScoreObj.Spawn(default.Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor);
|
||||
Amount += default.Amount;
|
||||
Owner.TakeInventory(parent,1);
|
||||
// absorb the extra damage too
|
||||
saved = HandleDamage(damage,damageType,flags);
|
||||
healed = max(0,saved-damage);
|
||||
saved = min(saved,damage);
|
||||
if ( amount <= saved ) saved = amount;
|
||||
newdamage -= saved;
|
||||
if ( healed > 0 ) Owner.GiveBody(healed);
|
||||
amount -= saved;
|
||||
damage = newdamage;
|
||||
}
|
||||
if ( swwm_accdamage ) SWWMScoreObj.Spawn(tgive,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor);
|
||||
}
|
||||
else if ( amount <= 0 )
|
||||
{
|
||||
if ( Owner.CheckLocalView() && (drainmsg != "") ) Console.Printf(StringTable.Localize(drainmsg));
|
||||
DepleteOrDestroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gives armor when used
|
||||
Class SWWMSpareArmor : Inventory abstract
|
||||
{
|
||||
Mixin SWWMAutoUseFix;
|
||||
Mixin SWWMUseToPickup;
|
||||
Mixin SWWMOverlapPickupSound;
|
||||
|
||||
Class<SWWMArmor> giveme;
|
||||
|
||||
Property GiveArmor : giveme;
|
||||
|
||||
override bool Use( bool pickup )
|
||||
{
|
||||
let cur = Owner.FindInventory(giveme);
|
||||
if ( !cur || (!pickup && (cur.Amount < cur.MaxAmount)) || (GetDefaultByType(giveme).Amount+cur.Amount <= cur.MaxAmount) )
|
||||
{
|
||||
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
|
||||
Owner.GiveInventory(giveme,GetDefaultByType(giveme).Amount);
|
||||
SWWMHandler.ArmorFlash(Owner.PlayerNumber());
|
||||
SWWMScoreObj.Spawn(GetDefaultByType(giveme).Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
+INVENTORY.INVBAR;
|
||||
+INVENTORY.ISARMOR;
|
||||
+INVENTORY.AUTOACTIVATE;
|
||||
Inventory.MaxAmount 5;
|
||||
Inventory.InterHubAmount 5;
|
||||
Inventory.PickupFlash "SWWMGreenPickupFlash";
|
||||
+FLOATBOB;
|
||||
FloatBobStrength 0.25;
|
||||
}
|
||||
}
|
||||
160
zscript/items/swwm_basehealth.zsc
Normal file
160
zscript/items/swwm_basehealth.zsc
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// Base class for all SWWM Health
|
||||
Class SWWMHealth : Inventory abstract
|
||||
{
|
||||
Mixin SWWMAutoUseFix;
|
||||
Mixin SWWMUseToPickup;
|
||||
Mixin SWWMOverlapPickupSound;
|
||||
|
||||
// can't use the Health class for whatever reason
|
||||
// nice parser you got there I guess?
|
||||
Class<Inventory> giveme;
|
||||
|
||||
Property GiveHealth : giveme;
|
||||
|
||||
override void AttachToOwner( Actor other )
|
||||
{
|
||||
Super.AttachToOwner(other);
|
||||
// find last health item that's better than us
|
||||
Inventory found = null;
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( !(i is 'SWWMHealth') || (i == self) || (GetDefaultByType(SWWMHealth(i).giveme).Amount < GetDefaultByType(giveme).Amount) ) continue;
|
||||
found = i;
|
||||
}
|
||||
if ( !found )
|
||||
{
|
||||
// find first item with health that's worse than us after it
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( (i == self) || !(i.Inv is 'SWWMHealth') ) continue;
|
||||
if ( GetDefaultByType(SWWMHealth(i.Inv).giveme).Amount > GetDefaultByType(giveme).Amount ) continue;
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
{
|
||||
// find last armor item, plating or collar
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( !(i is 'SWWMArmor') && !(i is 'AlmasteelPlating') && !(i is 'SayaCollar') ) continue;
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
{
|
||||
// check if the first item in inventory is a sandwich
|
||||
if ( other.Inv is 'GrilledCheeseSandwich' )
|
||||
{
|
||||
// we're good
|
||||
return;
|
||||
}
|
||||
// find first item next to a sandwich
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( (i == self) || !(i.Inv is 'GrilledCheeseSandwich') ) continue;
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
{
|
||||
// find last of either invinciball/ragekit/barrier power
|
||||
for ( Inventory i=other.Inv; i; i=i.Inv )
|
||||
{
|
||||
if ( !(i is 'InvinciballPower') && !(i is 'RagekitPower') && !(i is 'BarrierPower') ) continue;
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
if ( !found ) return;
|
||||
// place ourselves right after it
|
||||
Inventory saved = found.Inv;
|
||||
found.Inv = self;
|
||||
other.Inv = Inv;
|
||||
Inv = saved;
|
||||
}
|
||||
|
||||
override bool Use( bool pickup )
|
||||
{
|
||||
if ( Owner.Health >= GetDefaultByType(giveme).MaxAmount ) return false;
|
||||
// healing items won't get auto-used on pickup if their healing could "be wasted", unless they're powerup health (e.g. Refresher)
|
||||
if ( pickup && !bBIGPOWERUP && (Owner.Health+GetDefaultByType(giveme).Amount > GetDefaultByType(giveme).MaxAmount) ) return false;
|
||||
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
|
||||
SWWMHandler.HealthFlash(Owner.PlayerNumber());
|
||||
Owner.GiveInventory(giveme,GetDefaultByType(giveme).Amount);
|
||||
SWWMScoreObj.Spawn(GetDefaultByType(giveme).Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
AutoUseExtra(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// additional effects when automatically used
|
||||
// recursive: if true, the auto-use was called on another copy of the
|
||||
// item in a "stacked" heal. can be used to prevent certain
|
||||
// effects from happening multiple times in one go
|
||||
virtual void AutoUseExtra( bool recursive )
|
||||
{
|
||||
}
|
||||
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
if ( Amount <= 0 ) DepleteOrDestroy();
|
||||
}
|
||||
|
||||
override void AbsorbDamage( int damage, Name damageType, out int newdamage, Actor inflictor, Actor source, int flags )
|
||||
{
|
||||
if ( Owner.ApplyDamageFactor(damageType,damage) <= 0 )
|
||||
return; // this damage type is ignored by the player, so it does not affect us
|
||||
if ( damageType == 'EndLevel' )
|
||||
return; // don't trigger on endlevel damage
|
||||
bool shouldautouse = false;
|
||||
if ( swwm_enforceautousehealth == 1 ) shouldautouse = true;
|
||||
else if ( swwm_enforceautousehealth == -1 ) shouldautouse = false;
|
||||
else shouldautouse = CVar.GetCVar('swwm_autousehealth',Owner.player).GetBool();
|
||||
if ( !shouldautouse && !bBIGPOWERUP ) return; // powerup health is always auto-used
|
||||
if ( (Owner.Health-damage <= (GetDefaultByType(giveme).MaxAmount-GetDefaultByType(giveme).Amount)) )
|
||||
{
|
||||
newdamage = damage;
|
||||
// lesser healing items can't prevent lethal damage
|
||||
// bigger healing items only autoactivate on lethal damage
|
||||
if ( !bBIGPOWERUP && (Owner.Health-damage <= 0) )
|
||||
return;
|
||||
else if ( bBIGPOWERUP && (Owner.Health-damage > 0) )
|
||||
return;
|
||||
if ( (swwm_strictuntouchable == 1) && Owner.player )
|
||||
{
|
||||
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
||||
if ( hnd ) hnd.tookdamage[Owner.PlayerNumber()] = true;
|
||||
}
|
||||
if ( ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
|
||||
int tgive = 0;
|
||||
bool morethanonce = false;
|
||||
while ( (Amount > 0) && (newdamage > 0) )
|
||||
{
|
||||
if ( swwm_accdamage ) tgive += GetDefaultByType(giveme).Amount;
|
||||
else SWWMScoreObj.Spawn(GetDefaultByType(giveme).Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
newdamage = newdamage-GetDefaultByType(giveme).Amount;
|
||||
if ( newdamage < 0 ) Owner.GiveBody(-newdamage,GetDefaultByType(giveme).MaxAmount);
|
||||
newdamage = max(0,newdamage);
|
||||
AutoUseExtra(morethanonce);
|
||||
morethanonce = true;
|
||||
Amount--;
|
||||
}
|
||||
if ( swwm_accdamage ) SWWMScoreObj.Spawn(tgive,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
}
|
||||
else newdamage = damage;
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
+INVENTORY.INVBAR;
|
||||
+INVENTORY.ISHEALTH;
|
||||
+INVENTORY.AUTOACTIVATE;
|
||||
Inventory.MaxAmount 5;
|
||||
Inventory.InterHubAmount 5;
|
||||
Inventory.UseSound "misc/health_pkup";
|
||||
Inventory.PickupFlash "SWWMBluePickupFlash";
|
||||
+FLOATBOB;
|
||||
FloatBobStrength 0.25;
|
||||
}
|
||||
}
|
||||
88
zscript/items/swwm_baseitem.zsc
Normal file
88
zscript/items/swwm_baseitem.zsc
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// Inventory stuff
|
||||
Mixin Class SWWMAutoUseFix
|
||||
{
|
||||
override bool HandlePickup( Inventory item )
|
||||
{
|
||||
if ( GetClass() == item.GetClass() )
|
||||
{
|
||||
if ( Use(true) ) Amount--;
|
||||
// sell excess if there's a price
|
||||
if ( bALWAYSPICKUP && (Amount+item.Amount > MaxAmount) && (Stamina != 0) )
|
||||
{
|
||||
int sellprice = int(abs(Stamina)*.5);
|
||||
SWWMScoreObj.Spawn(sellprice,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2));
|
||||
SWWMCredits.Give(Owner.player,sellprice);
|
||||
if ( Owner.player )
|
||||
Console.Printf(StringTable.Localize(SWWMUtility.SellFemaleItem(item)?"$SWWM_SELLEXTRA_FEM":"$SWWM_SELLEXTRA"),Owner.player.GetUserName(),GetTag(),sellprice);
|
||||
}
|
||||
}
|
||||
return Super.HandlePickup(item);
|
||||
}
|
||||
}
|
||||
|
||||
Class CrossLineFinder : LineTracer
|
||||
{
|
||||
Array<Line> clines;
|
||||
Array<int> csides;
|
||||
|
||||
override ETraceStatus TraceCallback()
|
||||
{
|
||||
if ( (Results.HitType == TRACE_HitWall) && (Results.HitLine.activation&SPAC_Cross) )
|
||||
{
|
||||
clines.Push(Results.HitLine);
|
||||
csides.Push(Results.Side);
|
||||
}
|
||||
return TRACE_Skip;
|
||||
}
|
||||
}
|
||||
|
||||
Mixin Class SWWMUseToPickup
|
||||
{
|
||||
// allow pickup by use
|
||||
override bool Used( Actor user )
|
||||
{
|
||||
Vector3 itempos = Vec3Offset(0,0,Height/2),
|
||||
userpos = user.Vec2OffsetZ(0,0,user.player.viewz);
|
||||
// test vertical range
|
||||
Vector3 diff = level.Vec3Diff(user.Vec3Offset(0,0,user.Height/2),Vec3Offset(0,0,Height/2));
|
||||
double rang = user.player?PlayerPawn(user.player.mo).UseRange:(user.Height/2);
|
||||
if ( abs(diff.z) > rang ) return false;
|
||||
Touch(user);
|
||||
// we got picked up
|
||||
if ( bDestroyed || Owner || !bSPECIAL )
|
||||
{
|
||||
Vector3 tracedir = level.Vec3Diff(userpos,itempos);
|
||||
double dist = tracedir.length();
|
||||
tracedir /= dist;
|
||||
let cf = new("CrossLineFinder");
|
||||
cf.Trace(userpos,level.PointInSector(userpos.xy),tracedir,dist,0);
|
||||
// trigger all player cross lines found between user and item
|
||||
for ( int i=0; i<cf.clines.Size(); i++ )
|
||||
cf.clines[i].Activate(user,cf.csides[i],SPAC_Cross);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Mixin Class SWWMOverlapPickupSound
|
||||
{
|
||||
// overlap sounds
|
||||
override void PlayPickupSound( Actor toucher )
|
||||
{
|
||||
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
||||
if ( hnd )
|
||||
{
|
||||
if ( hnd.lastpickuptic[toucher.PlayerNumber()] == gametic )
|
||||
return; // don't play if picked up on the same exact tic (overlapping items)
|
||||
hnd.lastpickuptic[toucher.PlayerNumber()] = gametic;
|
||||
}
|
||||
double atten;
|
||||
int flags = CHANF_OVERLAP|CHANF_MAYBE_LOCAL;
|
||||
if ( bNoAttenPickupSound ) atten = ATTN_NONE;
|
||||
else atten = ATTN_NORM;
|
||||
if ( toucher && toucher.CheckLocalView() )
|
||||
flags |= CHANF_NOPAUSE;
|
||||
toucher.A_StartSound(PickupSound,CHAN_ITEM,flags,1.,atten);
|
||||
}
|
||||
}
|
||||
243
zscript/items/swwm_collectibles.zsc
Normal file
243
zscript/items/swwm_collectibles.zsc
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
// collectible items that may drop sometimes
|
||||
|
||||
Class SWWMCollectible : Inventory abstract
|
||||
{
|
||||
Mixin SWWMUseToPickup;
|
||||
|
||||
int avail;
|
||||
bool propagated;
|
||||
Class<SWWMItemGesture> gesture;
|
||||
|
||||
Property Availability : avail;
|
||||
Property GestureWeapon : gesture;
|
||||
|
||||
// minimum gametype requirements
|
||||
enum EAvailability
|
||||
{
|
||||
AVAIL_Strife = GAME_Strife,
|
||||
AVAIL_Hexen = AVAIL_Strife|GAME_Hexen,
|
||||
AVAIL_Heretic = AVAIL_Hexen|GAME_Heretic,
|
||||
AVAIL_All = AVAIL_Heretic|GAME_DoomChex
|
||||
};
|
||||
|
||||
Default
|
||||
{
|
||||
Inventory.PickupSound "menu/buyinv";
|
||||
Inventory.Amount 1;
|
||||
Inventory.MaxAmount 1;
|
||||
Inventory.PickupFlash "SWWMCyanPickupFlash";
|
||||
SWWMCollectible.Availability AVAIL_All;
|
||||
+INVENTORY.UNTOSSABLE;
|
||||
+INVENTORY.UNDROPPABLE;
|
||||
+INVENTORY.UNCLEARABLE;
|
||||
+INVENTORY.AUTOACTIVATE;
|
||||
+FLOATBOB;
|
||||
FloatBobStrength 0.25;
|
||||
Radius 8;
|
||||
Height 24;
|
||||
}
|
||||
override void PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
// delet ourselves if wrong iwad
|
||||
if ( !(gameinfo.gametype&avail) )
|
||||
Destroy();
|
||||
}
|
||||
override bool CanPickup( Actor toucher )
|
||||
{
|
||||
// no pickup if wrong iwad
|
||||
if ( !(gameinfo.gametype&avail) ) return false;
|
||||
return Super.CanPickup(toucher);
|
||||
}
|
||||
override string PickupMessage()
|
||||
{
|
||||
if ( Stamina > 0 )
|
||||
return StringTable.Localize(PickupMsg)..String.Format(" \cj(\cg¥\cf%d\cj)\c-",Stamina);
|
||||
return Super.PickupMessage();
|
||||
}
|
||||
override bool Use( bool pickup )
|
||||
{
|
||||
if ( Owner.player && !propagated )
|
||||
{
|
||||
if ( pickup && CVar.GetCVar('swwm_collectanim',Owner.player).GetBool() )
|
||||
SWWMGesture.SetSpecialGesture(Owner.player.mo,gesture);
|
||||
else if ( !pickup )
|
||||
SWWMGesture.SetSpecialGesture(Owner.player.mo,gesture,true);
|
||||
}
|
||||
// clean up the flag
|
||||
propagated = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
override void AttachToOwner( Actor other )
|
||||
{
|
||||
Super.AttachToOwner(other);
|
||||
// we're only attaching to the other players
|
||||
if ( propagated )
|
||||
return;
|
||||
// give credit
|
||||
if ( other.player && (Stamina > 0) )
|
||||
{
|
||||
SWWMScoreObj.Spawn(Stamina,other.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+other.Height/2));
|
||||
SWWMCredits.Give(other.player,Stamina);
|
||||
}
|
||||
// send to all other players
|
||||
for ( int i=0; i<MAXPLAYERS; i++ )
|
||||
{
|
||||
if ( !playeringame[i] || !players[i].mo || (i == other.PlayerNumber()) )
|
||||
continue;
|
||||
let c = SWWMCollectible(Spawn(GetClass(),pos));
|
||||
c.propagated = true;
|
||||
if ( !c.CallTryPickup(players[i].mo) )
|
||||
c.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
|
||||
// The collectibles
|
||||
Class GenericCube : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_PERFECTLYGENERIC";
|
||||
Inventory.PickupMessage "$T_PERFECTLYGENERIC";
|
||||
SWWMCollectible.GestureWeapon "GenericCubeGesture";
|
||||
Stamina 1000;
|
||||
}
|
||||
}
|
||||
Class AkariProject : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_AKARIPROJECT";
|
||||
Inventory.PickupMessage "$T_AKARIPROJECT";
|
||||
SWWMCollectible.GestureWeapon "AkariProjectGesture";
|
||||
Stamina 2000;
|
||||
Radius 4;
|
||||
Height 22;
|
||||
}
|
||||
}
|
||||
Class LoveSignalsCD : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_LOVESIGNALS";
|
||||
Inventory.PickupMessage "$T_LOVESIGNALS";
|
||||
SWWMCollectible.GestureWeapon "LoveSignalsCDGesture";
|
||||
Stamina 3000;
|
||||
Radius 4;
|
||||
Height 21;
|
||||
}
|
||||
}
|
||||
Class NutatcoBar : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_NUTATCO";
|
||||
Inventory.PickupMessage "$T_NUTATCO";
|
||||
SWWMCollectible.GestureWeapon "NutatcoBarGesture";
|
||||
Stamina 200;
|
||||
Radius 3;
|
||||
Height 22;
|
||||
}
|
||||
}
|
||||
Class FrispyCorn : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_FRISPYCORN";
|
||||
Inventory.PickupMessage "$T_FRISPYCORN";
|
||||
SWWMCollectible.GestureWeapon "FrispyCornGesture";
|
||||
Stamina 400;
|
||||
Radius 5;
|
||||
Height 23;
|
||||
}
|
||||
}
|
||||
Class SayaBean : SWWMCollectible
|
||||
{
|
||||
bool callout; // already called the player a perv for loading h-doom
|
||||
|
||||
Default
|
||||
{
|
||||
Tag "$T_SAYABEAN";
|
||||
Inventory.PickupMessage "$T_SAYABEAN";
|
||||
SWWMCollectible.GestureWeapon "SayaBeanGesture";
|
||||
Stamina 5000;
|
||||
Radius 6;
|
||||
Height 23;
|
||||
}
|
||||
}
|
||||
// Heretic
|
||||
Class DemoPlush : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_DEMOPLUSH";
|
||||
Inventory.PickupMessage "$T_DEMOPLUSH";
|
||||
SWWMCollectible.Availability AVAIL_Heretic;
|
||||
SWWMCollectible.GestureWeapon "DemoPlushGesture";
|
||||
Stamina 6000;
|
||||
Radius 12;
|
||||
Height 36;
|
||||
}
|
||||
}
|
||||
// Hexen
|
||||
Class KirinCummies : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_PEACH";
|
||||
Inventory.PickupMessage "$T_PEACH";
|
||||
SWWMCollectible.Availability AVAIL_Hexen;
|
||||
SWWMCollectible.GestureWeapon "KirinCummiesGesture";
|
||||
Stamina 300;
|
||||
Radius 3;
|
||||
Height 21;
|
||||
}
|
||||
}
|
||||
Class MilkBreads : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_MILKBREAD";
|
||||
Inventory.PickupMessage "$T_MILKBREAD";
|
||||
SWWMCollectible.Availability AVAIL_Hexen;
|
||||
SWWMCollectible.GestureWeapon "MilkBreadsGesture";
|
||||
Stamina 900;
|
||||
Radius 4;
|
||||
Height 21;
|
||||
}
|
||||
}
|
||||
Class KirinManga : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_KIRINMANGA";
|
||||
Inventory.PickupMessage "$T_KIRINMANGA";
|
||||
SWWMCollectible.Availability AVAIL_Hexen;
|
||||
SWWMCollectible.GestureWeapon "KirinMangaGesture";
|
||||
Stamina 1600;
|
||||
Radius 4;
|
||||
Height 22;
|
||||
}
|
||||
}
|
||||
Class KirinPlush : SWWMCollectible
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_KIRINPLUSH";
|
||||
Inventory.PickupMessage "$T_KIRINPLUSH";
|
||||
SWWMCollectible.Availability AVAIL_Hexen;
|
||||
SWWMCollectible.GestureWeapon "KirinPlushGesture";
|
||||
Stamina 8000;
|
||||
Radius 14;
|
||||
Height 37;
|
||||
}
|
||||
}
|
||||
12
zscript/items/swwm_collectibles_gesture.zsc
Normal file
12
zscript/items/swwm_collectibles_gesture.zsc
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// TODO them gestures
|
||||
Class GenericCubeGesture : SWWMItemGesture {}
|
||||
Class AkariProjectGesture : SWWMItemGesture {}
|
||||
Class LoveSignalsCDGesture : SWWMItemGesture {}
|
||||
Class NutatcoBarGesture : SWWMItemGesture {}
|
||||
Class FrispyCornGesture : SWWMItemGesture {}
|
||||
Class DemoPlushGesture : SWWMItemGesture {}
|
||||
Class SayaBeanGesture : SWWMItemGesture {}
|
||||
Class KirinCummiesGesture : SWWMItemGesture {}
|
||||
Class MilkBreadsGesture : SWWMItemGesture {}
|
||||
Class KirinMangaGesture : SWWMItemGesture {}
|
||||
Class KirinPlushGesture : SWWMItemGesture {}
|
||||
1125
zscript/items/swwm_funstuff.zsc
Normal file
1125
zscript/items/swwm_funstuff.zsc
Normal file
File diff suppressed because it is too large
Load diff
222
zscript/items/swwm_health.zsc
Normal file
222
zscript/items/swwm_health.zsc
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
// all the healing items go here
|
||||
Class HealthNugget : Health
|
||||
{
|
||||
Default
|
||||
{
|
||||
Inventory.Amount 1;
|
||||
Inventory.MaxAmount 200;
|
||||
}
|
||||
}
|
||||
|
||||
Class TetraHealth : Health
|
||||
{
|
||||
Default
|
||||
{
|
||||
Inventory.Amount 10;
|
||||
Inventory.MaxAmount 100;
|
||||
}
|
||||
}
|
||||
|
||||
Class CubeHealth : Health
|
||||
{
|
||||
Default
|
||||
{
|
||||
Inventory.Amount 20;
|
||||
Inventory.MaxAmount 100;
|
||||
}
|
||||
}
|
||||
|
||||
Class RefresherHealth : Health
|
||||
{
|
||||
Default
|
||||
{
|
||||
Inventory.Amount 100;
|
||||
Inventory.MaxAmount 500;
|
||||
}
|
||||
}
|
||||
Class RefresherRegen : Powerup
|
||||
{
|
||||
Default
|
||||
{
|
||||
Inventory.Icon "graphics/HUD/Icons/I_Refresher.png";
|
||||
Powerup.Duration -50;
|
||||
Powerup.Strength 10;
|
||||
+INVENTORY.ADDITIVETIME;
|
||||
}
|
||||
|
||||
override void EndEffect()
|
||||
{
|
||||
Super.EndEffect();
|
||||
if ( (EffectTics <= 0) && Owner && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_REFRESHER"));
|
||||
}
|
||||
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
if ( Owner && (Owner.health > 0) && !((EffectTics-5)%175) )
|
||||
{
|
||||
if ( Owner.GiveBody(int(Strength),500) )
|
||||
{
|
||||
SWWMScoreObj.Spawn(int(Strength),Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health);
|
||||
SWWMHandler.DoFlash(Owner,Color(32,224,128,255),10);
|
||||
Owner.A_StartSound("powerup/refresher",CHAN_ITEM,CHANF_LOCAL,.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Class HealthNuggetItem : SWWMHealth
|
||||
{
|
||||
override Inventory CreateCopy( Actor other )
|
||||
{
|
||||
// additional lore
|
||||
SWWMLoreLibrary.Add(other.player,"Nugget");
|
||||
return Super.CreateCopy(other);
|
||||
}
|
||||
Default
|
||||
{
|
||||
Tag "$T_NUGGETH";
|
||||
Stamina 200;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_HealthNugget.png";
|
||||
Inventory.PickupMessage "$T_NUGGETH";
|
||||
Inventory.MaxAmount 20;
|
||||
Inventory.InterHubAmount 20;
|
||||
SWWMHealth.GiveHealth "HealthNugget";
|
||||
+INVENTORY.ALWAYSPICKUP;
|
||||
Radius 4;
|
||||
Height 22;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 # -1 NoDelay
|
||||
{
|
||||
frame = Random[Nugget](0,7);
|
||||
}
|
||||
Stop;
|
||||
Dummy:
|
||||
XZW1 ABCDEFGH -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class HealthNuggetBundleSpawn : Actor
|
||||
{
|
||||
override void PostBeginPlay()
|
||||
{
|
||||
if ( bCOUNTSECRET ) level.total_secrets--;
|
||||
int bnd = Random[Bundle](2,3);
|
||||
for ( int i=0; i<bnd; i++ )
|
||||
{
|
||||
let a = Spawn("HealthNuggetItem",Vec3Angle(8,i*(360/bnd)));
|
||||
a.special = special;
|
||||
a.angle = i*(360/bnd);
|
||||
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
|
||||
if ( bCOUNTSECRET )
|
||||
{
|
||||
a.bCOUNTSECRET = true;
|
||||
level.total_secrets++;
|
||||
}
|
||||
}
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Class TetraHealthItem : SWWMHealth
|
||||
{
|
||||
override Inventory CreateCopy( Actor other )
|
||||
{
|
||||
// additional lore
|
||||
SWWMLoreLibrary.Add(other.player,"HealthGeom");
|
||||
return Super.CreateCopy(other);
|
||||
}
|
||||
Default
|
||||
{
|
||||
Tag "$T_TETRAHEALTH";
|
||||
Stamina 3000;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_HealthTetra.png";
|
||||
Inventory.PickupMessage "$T_TETRAHEALTH";
|
||||
Inventory.MaxAmount 15;
|
||||
Inventory.InterHubAmount 15;
|
||||
SWWMHealth.GiveHealth "TetraHealth";
|
||||
Radius 8;
|
||||
Height 24;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 # -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class CubeHealthItem : SWWMHealth
|
||||
{
|
||||
override Inventory CreateCopy( Actor other )
|
||||
{
|
||||
// additional lore
|
||||
SWWMLoreLibrary.Add(other.player,"HealthGeom");
|
||||
return Super.CreateCopy(other);
|
||||
}
|
||||
Default
|
||||
{
|
||||
Tag "$T_CUBEHEALTH";
|
||||
Stamina 8000;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_HealthCube.png";
|
||||
Inventory.PickupMessage "$T_CUBEHEALTH";
|
||||
Inventory.MaxAmount 10;
|
||||
Inventory.InterHubAmount 10;
|
||||
SWWMHealth.GiveHealth "CubeHealth";
|
||||
Radius 8;
|
||||
Height 24;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 # -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class RefresherItem : SWWMHealth
|
||||
{
|
||||
override Inventory CreateCopy( Actor other )
|
||||
{
|
||||
// additional lore
|
||||
SWWMLoreLibrary.Add(other.player,"Refresher");
|
||||
return Super.CreateCopy(other);
|
||||
}
|
||||
override void AutoUseExtra( bool recursive )
|
||||
{
|
||||
// regen effect doesn't stack if we autoactivated recursively
|
||||
if ( recursive ) return;
|
||||
let p = Powerup(Owner.FindInventory("RefresherRegen"));
|
||||
if ( p ) p.EffectTics += p.default.EffectTics;
|
||||
else Owner.GiveInventory("RefresherRegen",1);
|
||||
SWWMHandler.DoFlash(Owner,Color(80,224,128,255),20);
|
||||
}
|
||||
override bool Use( bool pickup )
|
||||
{
|
||||
// never get auto-used on pickup unless we're in deathmatch
|
||||
if ( pickup && !deathmatch ) return false;
|
||||
return Super.Use(pickup);
|
||||
}
|
||||
Default
|
||||
{
|
||||
Tag "$T_REFRESHER";
|
||||
Stamina 160000;
|
||||
Inventory.Icon "graphics/HUD/Icons/I_Refresher.png";
|
||||
Inventory.PickupMessage "$T_REFRESHER";
|
||||
Inventory.PickupSound "misc/p_pkup";
|
||||
Inventory.UseSound "powerup/refresheruse";
|
||||
SWWMHealth.GiveHealth "RefresherHealth";
|
||||
+COUNTITEM;
|
||||
+INVENTORY.BIGPOWERUP;
|
||||
+INVENTORY.ALWAYSPICKUP;
|
||||
Radius 6;
|
||||
Height 24;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 # -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
346
zscript/items/swwm_keys.zsc
Normal file
346
zscript/items/swwm_keys.zsc
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
// Key item replacements, including some for popular map packs
|
||||
|
||||
Class SWWMKey : Key abstract
|
||||
{
|
||||
Mixin SWWMOverlapPickupSound;
|
||||
Mixin SWWMUseToPickup;
|
||||
|
||||
bool propagated;
|
||||
Class<SWWMItemGesture> gesture;
|
||||
|
||||
Property GestureWeapon : gesture;
|
||||
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
if ( Icon.IsNull() )
|
||||
{
|
||||
// fetch icon from parent (if it exists)
|
||||
Class<Key> pc = Species;
|
||||
if ( !pc ) return;
|
||||
let p = GetDefaultByType(pc);
|
||||
Icon = p.Icon;
|
||||
}
|
||||
}
|
||||
|
||||
override void AttachToOwner( Actor other )
|
||||
{
|
||||
Super.AttachToOwner(other);
|
||||
// also attach the vanilla key that we replace, mainly for script compatibility
|
||||
Class<Key> pc = Species;
|
||||
if ( pc )
|
||||
{
|
||||
let p = Inventory(Spawn(pc));
|
||||
if ( Owner is 'Demolitionist' )
|
||||
Demolitionist(Owner).key_reentrant = true; // avoid infinite loop
|
||||
p.AttachToOwner(Owner);
|
||||
if ( Owner is 'Demolitionist' )
|
||||
Demolitionist(Owner).key_reentrant = false;
|
||||
}
|
||||
}
|
||||
|
||||
override bool Use( bool pickup )
|
||||
{
|
||||
if ( Owner.player && !propagated )
|
||||
{
|
||||
if ( pickup && CVar.GetCVar('swwm_collectanimkey',Owner.player).GetBool() )
|
||||
SWWMGesture.SetSpecialGesture(Owner.player.mo,gesture);
|
||||
else if ( !pickup )
|
||||
SWWMGesture.SetSpecialGesture(Owner.player.mo,gesture,true);
|
||||
}
|
||||
// clean up the flag
|
||||
propagated = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
+NOTDMATCH;
|
||||
+FLOATBOB;
|
||||
+INVENTORY.AUTOACTIVATE;
|
||||
FloatBobStrength 0.25;
|
||||
}
|
||||
}
|
||||
|
||||
Class SWWMRedCard : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_REDCARD";
|
||||
Species "RedCard";
|
||||
Inventory.PickupMessage "$T_REDCARD";
|
||||
Inventory.PickupFlash "SWWMRedPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMRedCardGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 AB 10;
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
Class SWWMYellowCard : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_YELLOWCARD";
|
||||
Species "YellowCard";
|
||||
Inventory.PickupMessage "$T_YELLOWCARD";
|
||||
Inventory.PickupFlash "SWWMPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMYellowCardGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 AB 10;
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
Class SWWMBlueCard : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_BLUECARD";
|
||||
Species "BlueCard";
|
||||
Inventory.PickupMessage "$T_BLUECARD";
|
||||
Inventory.PickupFlash "SWWMBluePickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMBlueCardGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 AB 10;
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
Class SWWMSilverCardKDiZD : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_SILVERCARD";
|
||||
Species "BlueSkull";
|
||||
Inventory.PickupMessage "$T_SILVERCARD";
|
||||
Inventory.PickupFlash "SWWMWhitePickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMSilverCardGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 AB 10;
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
Class SWWMGreenCardKDiZD : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_GREENCARD";
|
||||
Species "YellowSkull";
|
||||
Inventory.PickupMessage "$T_GREENCARD";
|
||||
Inventory.PickupFlash "SWWMGreenPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMGreenCardGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 AB 10;
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
Class SWWMOrangeCardKDiZD : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_ORANGECARD";
|
||||
Species "RedSkull";
|
||||
Inventory.PickupMessage "$T_ORANGECARD";
|
||||
Inventory.PickupFlash "SWWMPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMOrangeCardGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 AB 10;
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
Class SWWMGreenCard : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_GREENCARD";
|
||||
Species "GreenCard";
|
||||
Inventory.PickupMessage "$T_GREENCARD";
|
||||
Inventory.PickupFlash "SWWMGreenPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMGreenCardGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 AB 10;
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
// more Doom key color variants will be implemented as needed
|
||||
|
||||
Class SWWMRedSkull : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_REDSKULL";
|
||||
Species "RedSkull";
|
||||
Inventory.PickupMessage "$T_REDSKULL";
|
||||
Inventory.PickupFlash "SWWMRedPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMRedSkullGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class SWWMBlueSkull : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_BLUESKULL";
|
||||
Species "BlueSkull";
|
||||
Inventory.PickupMessage "$T_BLUESKULL";
|
||||
Inventory.PickupFlash "SWWMBluePickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMBlueSkullGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class SWWMYellowSkull : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_YELLOWSKULL";
|
||||
Species "YellowSkull";
|
||||
Inventory.PickupMessage "$T_YELLOWSKULL";
|
||||
Inventory.PickupFlash "SWWMPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMYellowSkullGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
|
||||
Class SWWMKeyGreen : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_KEYGREEN";
|
||||
Species "KeyGreen";
|
||||
Inventory.PickupMessage "$T_KEYGREEN";
|
||||
Inventory.PickupFlash "SWWMGreenPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMGreenKeyGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class SWWMKeyBlue : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_KEYBLUE";
|
||||
Species "KeyBlue";
|
||||
Inventory.PickupMessage "$T_KEYBLUE";
|
||||
Inventory.PickupFlash "SWWMBluePickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMBlueKeyGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class SWWMKeyYellow : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_KEYYELLOW";
|
||||
Species "KeyYellow";
|
||||
Inventory.PickupMessage "$T_KEYYELLOW";
|
||||
Inventory.PickupFlash "SWWMPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMYellowKeyGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class SWWMKeyRed : SWWMKey
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_KEYRED";
|
||||
Species "KeyRed";
|
||||
Inventory.PickupMessage "$T_KEYRED";
|
||||
Inventory.PickupFlash "SWWMRedPickupFlash";
|
||||
SWWMKey.GestureWeapon "SWWMRedKeyGesture";
|
||||
Radius 10;
|
||||
Height 25;
|
||||
}
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
XZW1 A -1;
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
|
||||
// HEXDD thingy
|
||||
Class SWWMChaosSphere : Key
|
||||
{
|
||||
Default
|
||||
{
|
||||
Tag "$T_CHAOSSPHERE";
|
||||
Inventory.InterHubAmount 1; // don't strip, this thing is always kept
|
||||
+INVENTORY.UNDROPPABLE;
|
||||
+INVENTORY.UNTOSSABLE;
|
||||
+INVENTORY.UNCLEARABLE;
|
||||
}
|
||||
}
|
||||
140
zscript/items/swwm_keys_gesture.zsc
Normal file
140
zscript/items/swwm_keys_gesture.zsc
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
// Key gestures
|
||||
// (they all use the same exact animations, just with the object changed)
|
||||
// (yeah, I'm lazy, and there's a lot of keys)
|
||||
Class SWWMKeyGesture : SWWMItemGesture abstract
|
||||
{
|
||||
// due to specifics™ we have to handle the punching here
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
if ( !Owner || !Owner.player || (Owner.player.Health <= 0) || (Owner.player.ReadyWeapon != self) )
|
||||
return;
|
||||
PSprite psp = Owner.player.FindPSPrite(PSP_WEAPON+1);
|
||||
if ( !(Owner.player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK|BT_USER1)) && !psp )
|
||||
{
|
||||
// not punching, move weapon back
|
||||
psp = Owner.player.FindPSPrite(PSP_WEAPON);
|
||||
if ( psp )
|
||||
{
|
||||
psp.oldx = psp.x;
|
||||
psp.x = max(0,psp.x-8);
|
||||
psp.oldy = psp.y;
|
||||
psp.y = min(32,psp.y+4);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ( psp )
|
||||
{
|
||||
// already punching, let's shift the weapon away
|
||||
psp = Owner.player.FindPSPrite(PSP_WEAPON);
|
||||
if ( psp )
|
||||
{
|
||||
// shift away from center to center
|
||||
psp.oldx = psp.x;
|
||||
psp.x = min(70,psp.x+8);
|
||||
psp.oldy = psp.y;
|
||||
psp.y = max(16,psp.y-4);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// start punch
|
||||
if ( Owner.player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK|BT_USER1) )
|
||||
{
|
||||
psp = Owner.player.FindPSPrite(PSP_WEAPON);
|
||||
if ( psp && (psp.CurState == FindState("WaitingForEnd")) )
|
||||
return;
|
||||
Owner.player.SetPSprite(PSP_WEAPON+1,FindState("Punch"));
|
||||
psp = Owner.player.FindPSPrite(PSP_WEAPON+1);
|
||||
if ( psp )
|
||||
{
|
||||
psp.bAddWeapon = false;
|
||||
psp.bAddBob = false;
|
||||
psp.x = -50;
|
||||
psp.y = 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
States
|
||||
{
|
||||
Fire:
|
||||
XZW1 A 3 A_Jump(128,"AltFire","AltFire2");
|
||||
XZW1 B 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW1 CDEF 3;
|
||||
XZW1 GHIJKLMNO 4;
|
||||
XZW1 P 3 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW1 QRST 3;
|
||||
Goto WaitingForEnd;
|
||||
AltFire:
|
||||
XZW1 A 3 A_Jump(128,"Fire","AltFire2");
|
||||
XZW1 U 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW1 VWX 3;
|
||||
XZW1 YZ 4;
|
||||
XZW2 ABC 4;
|
||||
XZW2 D 4 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP,pitch:.7);
|
||||
XZW2 EFGHIJ 4;
|
||||
XZW2 KL 3;
|
||||
XZW2 M 3 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW2 NOPQR 3;
|
||||
Goto WaitingForEnd;
|
||||
AltFire2:
|
||||
XZW1 A 3;
|
||||
XZW2 S 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW2 TUVWX 3;
|
||||
XZW2 YZ 4;
|
||||
XZW3 ABCDE 4;
|
||||
XZW3 F 2 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW3 GHI 2;
|
||||
XZW3 JKL 3;
|
||||
XZW3 MN 2;
|
||||
XZW3 O 2 A_StartSound("demolitionist/petting",CHAN_WEAPON,CHANF_OVERLAP,.4);
|
||||
XZW3 PQ 2;
|
||||
XZW3 RS 4;
|
||||
XZW3 T 4 A_StartSound("demolitionist/handsdown",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
XZW3 UV 4;
|
||||
XZW3 WXY 3;
|
||||
Goto WaitingForEnd;
|
||||
WaitingForEnd:
|
||||
XZW1 A 1 A_JumpIf(!player.FindPSprite(PSP_WEAPON+1),1);
|
||||
Wait;
|
||||
XZW1 A -1 A_FinishGesture();
|
||||
Stop;
|
||||
// overlay for melee
|
||||
Punch:
|
||||
XZW0 ABC 1;
|
||||
PunchHold:
|
||||
XZW0 D 1
|
||||
{
|
||||
A_PlayerMelee(true);
|
||||
A_StartSound("demolitionist/swing",CHAN_WEAPON,CHANF_OVERLAP);
|
||||
A_Parry(9);
|
||||
}
|
||||
XZW0 EF 1;
|
||||
XZW0 G 1 A_Melee();
|
||||
XZW0 HIJKLMN 2;
|
||||
XZW0 A 0
|
||||
{
|
||||
if ( player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK|BT_USER1) )
|
||||
{
|
||||
let psp = player.FindPSprite(PSP_WEAPON);
|
||||
if ( psp && (psp.CurState != ResolveState("WaitingForEnd")) )
|
||||
return ResolveState("PunchHold");
|
||||
}
|
||||
return ResolveState(null);
|
||||
}
|
||||
Stop;
|
||||
}
|
||||
}
|
||||
Class SWWMRedCardGesture : SWWMKeyGesture {}
|
||||
Class SWWMYellowCardGesture : SWWMKeyGesture {}
|
||||
Class SWWMBlueCardGesture : SWWMKeyGesture {}
|
||||
Class SWWMSilverCardGesture : SWWMKeyGesture {}
|
||||
Class SWWMGreenCardGesture : SWWMKeyGesture {}
|
||||
Class SWWMOrangeCardGesture : SWWMKeyGesture {}
|
||||
Class SWWMRedSkullGesture : SWWMKeyGesture {}
|
||||
Class SWWMYellowSkullGesture : SWWMKeyGesture {}
|
||||
Class SWWMBlueSkullGesture : SWWMKeyGesture {}
|
||||
Class SWWMGreenKeyGesture : SWWMKeyGesture {}
|
||||
Class SWWMBlueKeyGesture : SWWMKeyGesture {}
|
||||
Class SWWMYellowKeyGesture : SWWMKeyGesture {}
|
||||
Class SWWMRedKeyGesture : SWWMKeyGesture {}
|
||||
2014
zscript/items/swwm_powerups.zsc
Normal file
2014
zscript/items/swwm_powerups.zsc
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue