Implement "dropped item magnet".

This commit is contained in:
Mari the Deer 2022-08-15 15:05:33 +02:00
commit 3fcab013b7
11 changed files with 215 additions and 47 deletions

View file

@ -944,8 +944,6 @@ Class Chancebox : Actor
// spawn another smaller chancebox
// (chance increases for the inner box, up until a scale factor of 50% is reached)
let a = Spawn("Chancebox",pos+(0,0,3*scale.y));
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
a.angle = angle;
a.scale *= scale.x-.125;
@ -964,7 +962,13 @@ Class Chancebox : Actor
if ( !vipitemdrop ) vipitemdrop = "GrilledCheeseSandwich";
let a = Spawn((!Random[Chancebox](0,2)&&vipammodrop)?vipammodrop:vipitemdrop,pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
}
else if ( !Random[Chancebox](0,2) && SWWMUtility.CheckNeedsItem("ItamexHammer") )
{
// sometimes mapsets don't have chainsaw spawns for whatever reason
let a = Spawn("ItamexHammer",pos);
a.bDROPPED = false;
a.vel.z = FRandom[Chancebox](2,4);
}
else if ( !Random[Chancebox](0,2) && SWWMUtility.ItemExists("CandyGun") )
@ -972,8 +976,7 @@ Class Chancebox : Actor
for ( int i=0; i<=6; i++ )
{
let a = Spawn((i==0)?"CandyGun":"CandyGunBullets",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = (i!=0);
a.vel.z = FRandom[Chancebox](2,4);
if ( i > 0 ) a.vel.xy = (cos(i*60),sin(i*60))*FRandom[Chancebox](1,2);
}
@ -983,16 +986,14 @@ Class Chancebox : Actor
for ( int i=0; i<3; i++ )
{
let a = Spawn("SilverBullets2",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*120),sin(i*120))*FRandom[Chancebox](1,2);
}
for ( int i=0; i<6; i++ )
{
let a = Spawn("SilverBullets",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*60),sin(i*60))*FRandom[Chancebox](3,4);
}
@ -1000,65 +1001,87 @@ Class Chancebox : Actor
else if ( Random[Chancebox](0,1) && SWWMUtility.ItemExists("Hellblazer") )
{
let a = Spawn("HellblazerWarheads",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
for ( int i=0; i<3; i++ )
{
a = Spawn("HellblazerRavagers",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*120),sin(i*120))*FRandom[Chancebox](1,2);
}
for ( int i=0; i<5; i++ )
{
a = Spawn("HellblazerCrackshots",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*72),sin(i*72))*FRandom[Chancebox](3,4);
}
for ( int i=0; i<8; i++ )
{
a = Spawn("HellblazerMissiles",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*45),sin(i*45))*FRandom[Chancebox](5,6);
}
}
else if ( Random[Chancebox](0,1) && SWWMUtility.ItemExists("HeavyMahSheenGun") )
{
let a = Spawn("SheenBigAmmo",pos);
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
for ( int i=0; i<5; i++ )
{
a = Spawn("SheenSmallAmmo",pos);
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*72),sin(i*72))*FRandom[Chancebox](3,4);
}
}
else if ( Random[Chancebox](0,1) && SWWMUtility.ItemExists("Spreadgun") )
{
let a = Spawn("BlackShell",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
for ( int i=0; i<8; i++ )
{
a = Spawn((i%2)?"PurpleShell":"BlueShell",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*72),sin(i*72))*FRandom[Chancebox](2,3);
a.vel.xy = (cos(i*45),sin(i*45))*FRandom[Chancebox](2,3);
}
for ( int i=0; i<12; i++ )
{
a = Spawn((i%2)?"RedShell":"GreenShell",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*30),sin(i*30))*FRandom[Chancebox](4,5);
}
}
else if ( Random[Chancebox](0,1) && SWWMUtility.ItemExists("Wallbuster") )
{
for ( int i=0; i<12; i++ )
{
let a = Spawn((i%2)?"PurpleShell":"BlueShell",pos);
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*30),sin(i*30))*FRandom[Chancebox](2,3);
}
for ( int i=0; i<20; i++ )
{
let a = Spawn((i%2)?"RedShell":"GreenShell",pos);
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,4);
a.vel.xy = (cos(i*18),sin(i*18))*FRandom[Chancebox](4,5);
}
}
else if ( Random[Chancebox](0,1) )
{
Class<Actor> which = Random[Chancebox](1,0)?"HealthNuggetItem":"ArmorNuggetItem";
for ( int i=0; i<20; i++ )
{
let a = Spawn(which,pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = true;
a.vel.z = FRandom[Chancebox](2,8);
a.vel.xy = (cos(i*18),sin(i*18))*FRandom[Chancebox](1,8);
}
@ -1068,8 +1091,7 @@ Class Chancebox : Actor
for ( int i=0; i<=15; i++ )
{
let a = Spawn((i==0)?"RefresherItem":(i%3)?"HealthNuggetItem":"ArmorNuggetItem",pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.bDROPPED = (i!=0);
a.vel.z = FRandom[Chancebox](2,4);
if ( i > 0 ) a.vel.xy = (cos(i*24),sin(i*24))*FRandom[Chancebox](1,2);
}
@ -1080,7 +1102,6 @@ Class Chancebox : Actor
// pop one at random
let a = Spawn(candidates[Random[Chancebox](0,candidates.Size()-1)],pos);
a.bDROPPED = false;
a.bNOGRAVITY = false;
a.vel.z = FRandom[Chancebox](2,4);
}
int numpt = Random[ExploS](16,32);

View file

@ -118,6 +118,10 @@ Class Demolitionist : PlayerPawn
transient CVar tagcolor;
int oldtagcolor;
transient int magtime;
SWWMMagItem magitem;
int magitem_cnt;
Default
{
Tag "$T_DEMOLITIONIST";
@ -857,6 +861,75 @@ Class Demolitionist : PlayerPawn
rings += 2;
}
}
void CheckItemMagnet()
{
if ( magtime > 40 )
{
if ( !(player.cmd.buttons&BT_USE) || swwm_usetopickup )
{
magtime = 0;
SWWMMagItem mi = magitem;
while ( mi )
{
let next = mi.next;
mi.Destroy();
mi = next;
}
magitem_cnt = 0;
return;
}
if ( !swwm_usetopickup )
{
let bt = BlockThingsIterator.Create(self,400);
while ( bt.Next() )
{
let t = bt.Thing;
if ( !t || !(t is 'Inventory') || !t.bSPECIAL || !t.bDROPPED || t.bINVISIBLE || Inventory(t).Owner || !SWWMUtility.SphereIntersect(t,pos,400) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
continue;
let i = Inventory(t);
Class<Inventory> cls = i.GetClass();
if ( i is 'Ammo' ) cls = Ammo(i).GetParentAmmo();
else if ( i is 'MaGammo' ) cls = MagAmmo(i).GetParentMagAmmo();
let oi = FindInventory(cls);
if ( !i.bALWAYSPICKUP && oi && (oi.Amount >= oi.MaxAmount) ) continue;
bool addme = true;
for ( SWWMMagItem mi=magitem; mi; mi=mi.next )
{
if ( mi.item != i ) continue;
addme = false;
break;
}
if ( !addme ) continue;
let nmi = new("SWWMMagItem");
nmi.target = self;
nmi.item = i;
nmi.next = magitem;
i.A_StartSound("misc/magitem",CHAN_AMBEXTRA,CHANF_LOOP,.2,3.,.2);
magitem = nmi;
magitem_cnt++;
}
bt.Destroy();
}
SWWMMagItem itm = magitem;
SWWMMagItem prev = null, next;
while ( itm )
{
next = itm.next;
if ( itm.Tick() )
{
if ( prev ) prev.next = next;
else magitem = next;
if ( itm.item ) itm.item.A_StopSound(CHAN_AMBEXTRA);
itm.Destroy();
magitem_cnt--;
}
else prev = itm;
itm = next;
}
return;
}
if ( player.cmd.buttons&BT_USE ) magtime++;
}
void CheckUnderwaterAmb( bool restore = false )
{
Vector3 headpos = Vec3Offset(0,0,player.viewheight);
@ -1227,6 +1300,7 @@ Class Demolitionist : PlayerPawn
}
CheckUnderwaterAmb();
SenseItems();
CheckItemMagnet();
if ( vel.length() > mystats.topspeed ) mystats.topspeed = vel.length();
if ( vel.length() > ((3600*GameTicRate)/32000.) )
SWWMUtility.AchievementProgress("sanic",int((vel.length()*3600*GameTicRate)/32000.),player);
@ -3219,6 +3293,23 @@ Class Demolitionist : PlayerPawn
{
// clean up attached actors
if ( selflight ) selflight.Destroy();
// clean up our objects
SWWMItemSense si = itemsense;
while ( si )
{
let next = si.next;
si.Destroy();
si = next;
}
itemsense_cnt = 0;
SWWMMagItem mi = magitem;
while ( mi )
{
let next = mi.next;
mi.Destroy();
mi = next;
}
magitem_cnt = 0;
// disable death exits
if ( player && (player.playerstate == PST_DEAD) )
{

View file

@ -223,6 +223,41 @@ Class AmmoOrbTrail : SlayerOrbTrail
}
}
// simple object for moving a dropped item towards the player
Class SWWMMagItem play
{
SWWMMagItem next;
Inventory item;
Demolitionist target;
bool Tick()
{
if ( !target || (target.Health <= 0) ) return true;
if ( !item || item.Owner || !item.bSPECIAL ) return true;
Class<Inventory> cls = item.GetClass();
if ( item is 'Ammo' ) cls = Ammo(item).GetParentAmmo();
else if ( item is 'MaGammo' ) cls = MagAmmo(item).GetParentMagAmmo();
let oi = target.FindInventory(cls);
if ( !item.bALWAYSPICKUP && oi && (oi.Amount >= oi.MaxAmount) ) return true;
Vector3 dirto = level.Vec3Diff(item.pos,target.Vec3Offset(0,0,target.height/2));
double dist = dirto.length();
if ( SWWMUtility.BoxIntersect(item,target) )
{
item.Touch(target);
return false;
}
dirto /= dist;
double fact = clamp(dist/400.,0.,1.)**.5;
item.vel += dirto*SWWMUtility.Lerp(4.,.1,fact);
item.A_SoundVolume(CHAN_AMBEXTRA,1.-.8*fact);
item.A_SoundPitch(CHAN_AMBEXTRA,SWWMUtility.Lerp(1.5,.2,fact));
let s = item.Spawn("SWWMHalfSmoke",item.pos);
s.vel += dirto*8.*fact;
s.alpha *= .2*fact;
return false;
}
}
Class DashTrail : Actor
{
Default