First batch of changes:
- Fix score being reset on coop respawn. - Remove slight vertical offset of ground dash, not needed when we have NOFRICTION. - Disable stair downstepping while dashing. - Add crit sound for buttslams when they kill something. - Clean up some more stuff on map transitions (e.g.: dash/stomp canceling) - Korax messages show with a colored name now, for zazz. - Removed hitscan parrying, as it's odd and unpredictable. - Adjusted how wall detection works in dashes, should work better with stairs. - Allow down-dashes in mid-air when jumping is disabled, so you can still groundslam.
This commit is contained in:
parent
6cd065cf7c
commit
75e3ef30fc
8 changed files with 73 additions and 97 deletions
1
TODO.md
1
TODO.md
|
|
@ -3,7 +3,6 @@
|
|||
- Extra Demolitionist animations (swimming, additional gestures)
|
||||
- Dual wielding Explodium Gun
|
||||
- Quick grenade function (Explodium Mag)
|
||||
- Parrying for hitscan weapons (currently parrying only handles vanilla LineAttack)
|
||||
- Fun options
|
||||
- Omnibusting (all weapons can bust walls)
|
||||
- Infinite fuel
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
[default]
|
||||
SWWM_MODVER="\chSWWM \cwGZ\c- 0.9b r549 (Tue 15 Sep 19:18:10 CEST 2020)";
|
||||
SWWM_MODVER="\chSWWM \cwGZ\c- 0.9b r549 (Sat 19 Sep 11:20:53 CEST 2020)";
|
||||
|
|
|
|||
|
|
@ -357,6 +357,7 @@ $random demolitionist/whitm { demolitionist/whitm1 demolitionist/whitm2 demoliti
|
|||
demolitionist/whitl1 sounds/demolitionist/demowhitl1.ogg
|
||||
demolitionist/whitl2 sounds/demolitionist/demowhitl2.ogg
|
||||
$random demolitionist/whitl { demolitionist/whitl1 demolitionist/whitl2 }
|
||||
demolitionist/buttslam sounds/demolitionist/demobutt.ogg
|
||||
|
||||
$playersound demolitionist neutral *grunt DSEMPTY
|
||||
$playeralias demolitionist neutral *pain100 demolitionist/lopain
|
||||
|
|
|
|||
BIN
sounds/demolitionist/demobutt.ogg
Normal file
BIN
sounds/demolitionist/demobutt.ogg
Normal file
Binary file not shown.
|
|
@ -571,7 +571,7 @@ Class SWWMHandler : EventHandler
|
|||
|
||||
override void PlayerEntered( PlayerEvent e )
|
||||
{
|
||||
// create some static thinkers for this player
|
||||
// create some static thinkers for this player if needed
|
||||
PlayerInfo p = players[e.playernumber];
|
||||
SWWMTradeHistory th = SWWMTradeHistory.Find(p);
|
||||
if ( !th )
|
||||
|
|
@ -634,13 +634,30 @@ Class SWWMHandler : EventHandler
|
|||
// reset combat tracker
|
||||
if ( !swwm_notrack )
|
||||
SWWMCombatTracker.Spawn(players[e.playernumber].mo);
|
||||
// initialize some player vars
|
||||
if ( p.mo is 'Demolitionist' )
|
||||
{
|
||||
// reinitialize
|
||||
Demolitionist(p.mo).dashfuel = Demolitionist(p.mo).default.dashfuel;
|
||||
Demolitionist(p.mo).last_boost = 0;
|
||||
Demolitionist(p.mo).last_kick = 0;
|
||||
// cancel dash/boost
|
||||
p.mo.A_StopSound(CHAN_JETPACK);
|
||||
Demolitionist(p.mo).fuelcooldown = 0.;
|
||||
Demolitionist(p.mo).dashcooldown = 0.;
|
||||
Demolitionist(p.mo).dashboost = 0.;
|
||||
Demolitionist(p.mo).dashsnd = false;
|
||||
// prevent sudden stomping if we were previously falling
|
||||
Demolitionist(p.mo).lastvelz = p.mo.vel.z;
|
||||
// early cancel gestures
|
||||
if ( p.ReadyWeapon is 'SWWMGesture' )
|
||||
{
|
||||
p.PendingWeapon = SWWMGesture(p.ReadyWeapon).formerweapon;
|
||||
p.SetPSprite(PSP_WEAPON,p.ReadyWeapon.ResolveState("Deselect"));
|
||||
}
|
||||
}
|
||||
// reset score (optional) if inventory should be cleared
|
||||
if ( level.removeitems && !e.IsReturn && swwm_resetscore )
|
||||
c.credits = c.hcredits = 0;
|
||||
}
|
||||
|
||||
override void PlayerRespawned( PlayerEvent e )
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ Class SWWMStatusBar : BaseStatusBar
|
|||
{
|
||||
// treat as chat message
|
||||
printlevel = PRINT_CHAT;
|
||||
outline = "Korax: "..outline;
|
||||
outline = "\cmKorax\c-: "..outline;
|
||||
}
|
||||
let m = new("MsgLine");
|
||||
m.str = outline.Left(outline.Length()-1); // strip newline
|
||||
|
|
|
|||
|
|
@ -739,13 +739,7 @@ Class ParryField : Actor
|
|||
+NOCLIP;
|
||||
+DONTSPLASH;
|
||||
+NOTELEPORT;
|
||||
+SHOOTABLE;
|
||||
+NONSHOOTABLE;
|
||||
+NOBLOOD;
|
||||
+DONTTHRUST;
|
||||
+NOINTERACTION;
|
||||
Health int.max;
|
||||
Mass int.max;
|
||||
Radius 20;
|
||||
Height 40;
|
||||
}
|
||||
|
|
@ -814,73 +808,6 @@ Class ParryField : Actor
|
|||
}
|
||||
if ( --special1 <= 0 ) Destroy();
|
||||
}
|
||||
|
||||
override bool CanCollideWith( Actor other, bool passive )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
|
||||
{
|
||||
if ( (flags&DMG_INFLICTOR_IS_PUFF) && (source != master) )
|
||||
{
|
||||
Vector3 vdir = (cos(angle),sin(angle),0);
|
||||
Vector3 vpos = inflictor.pos; // puff goes here
|
||||
let raging = RagekitPower(master.FindInventory("RagekitPower"));
|
||||
let i = Spawn(raging?"BigPunchImpact":"PunchImpact",vpos);
|
||||
if ( raging ) raging.DoHitFX();
|
||||
i.angle = angle+180;
|
||||
i.bAMBUSH = true;
|
||||
// deflect hitscan
|
||||
A_StartSound("misc/ricochet",CHAN_VOICE,CHANF_OVERLAP,.7);
|
||||
A_QuakeEx(3,3,3,10,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:.2);
|
||||
A_StartSound("demolitionist/parry",CHAN_WEAPON);
|
||||
double mult = 1.5;
|
||||
if ( raging ) mult = 8.;
|
||||
if ( (level.maptime > lasteggtic) && !Random[Parry](0,4) )
|
||||
{
|
||||
for ( int i=1; i<6; i++ )
|
||||
{
|
||||
let r = Spawn("ParryRing",vpos);
|
||||
r.specialf1 = i*.04;
|
||||
}
|
||||
mult *= 2.;
|
||||
A_StartSound("misc/soulsparry",CHAN_ITEM,CHANF_OVERLAP,1.,.5);
|
||||
lasteggtic = level.maptime+5;
|
||||
}
|
||||
// three options:
|
||||
switch ( Random[Parry](0,7) )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
// 1. just block the bullet, making it bounce off
|
||||
let b = Spawn("ReflectedBullet",vpos);
|
||||
b.angle = angle;
|
||||
b.target = master;
|
||||
b.vel = (-vdir+(FRandom[Parry](-.4,.4),FRandom[Parry](-.4,.4),FRandom[Parry](-.4,.4))).unit()*FRandom[Parry](1,2)*mult+(0,0,4);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
// 2. ricochet in random direction
|
||||
Vector3 rdir = (-vdir+(FRandom[Parry](-.6,.6),FRandom[Parry](-.6,.6),FRandom[Parry](-.6,.6))).unit();
|
||||
bSHOOTABLE = false;
|
||||
master.LineAttack(atan2(rdir.y,rdir.x),8000,asin(-rdir.z),int(damage*mult),mod,inflictor.GetClass(),LAF_ABSPOSITION,null,vpos.z,vpos.x,vpos.y);
|
||||
bSHOOTABLE = true;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
// 3. ricochet directly back to source
|
||||
Vector3 tdir = source?(level.Vec3Diff(vpos,source.Vec3Offset(0,0,source.height/2))).unit():(-vdir);
|
||||
bSHOOTABLE = false;
|
||||
master.LineAttack(atan2(tdir.y,tdir.x),8000,asin(-tdir.z),int(damage*mult),mod,inflictor.GetClass(),LAF_ABSPOSITION,null,vpos.z,vpos.x,vpos.y);
|
||||
bSHOOTABLE = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Class UseList
|
||||
|
|
|
|||
|
|
@ -275,14 +275,7 @@ Class Demolitionist : PlayerPawn
|
|||
override void GiveDefaultInventory()
|
||||
{
|
||||
Super.GiveDefaultInventory();
|
||||
// reset score (optional)
|
||||
if ( swwm_resetscore )
|
||||
{
|
||||
let creds = SWWMCredits.Find(player);
|
||||
if ( creds ) creds.credits = creds.hcredits = 0;
|
||||
}
|
||||
// preloaded gun
|
||||
let dp = DeepImpact(FindInventory("DeepImpact"));
|
||||
let eg = ExplodiumGun(FindInventory("ExplodiumGun"));
|
||||
if ( !eg ) return;
|
||||
eg.clipcount = 7;
|
||||
|
|
@ -719,7 +712,13 @@ Class Demolitionist : PlayerPawn
|
|||
if ( raging ) flg |= DMG_FOILINVUL;
|
||||
if ( !a.player && !a.bDONTBLAST ) a.bBLASTED = true;
|
||||
int dmg = int(15+spd*2.5);
|
||||
if ( dir dot viewdir < -.3 ) dmg *= 3; // BUTTSLAM
|
||||
bool buttslam = false;
|
||||
// BUTTSLAM
|
||||
if ( dir dot viewdir < -.3 )
|
||||
{
|
||||
dmg *= 3;
|
||||
buttslam = true;
|
||||
}
|
||||
if ( a.bSHOOTABLE )
|
||||
{
|
||||
dmg = a.DamageMobj(self,self,dmg,'Dash',flg);
|
||||
|
|
@ -728,6 +727,12 @@ Class Demolitionist : PlayerPawn
|
|||
a.TraceBleed(dmg,self);
|
||||
a.SpawnBlood(level.Vec3Offset(pos,diff/2),atan2(dir.y,dir.x)+180,dmg);
|
||||
}
|
||||
if ( buttslam && (!a || (a.Health <= 0)) )
|
||||
{
|
||||
A_StartSound("demolitionist/buttslam",CHAN_DAMAGE,CHAN_OVERLAP,1.,.2);
|
||||
Spawn("SWWMItemFog",level.Vec3Offset(pos,diff/2));
|
||||
A_QuakeEx(8,8,8,8,0,3000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollIntensity:1.);
|
||||
}
|
||||
}
|
||||
if ( raging )
|
||||
{
|
||||
|
|
@ -760,7 +765,13 @@ Class Demolitionist : PlayerPawn
|
|||
// see if we can bust it
|
||||
let tempme = new("LineTracer"); // gross hack to pass needed data
|
||||
int dmg = int(128+spd*20);
|
||||
if ( dir dot viewdir < -.3 ) dmg *= 3; // BUTTSLAM
|
||||
bool buttslam = false;
|
||||
// BUTTSLAM
|
||||
if ( dir dot viewdir < -.3 )
|
||||
{
|
||||
dmg *= 3;
|
||||
buttslam = true;
|
||||
}
|
||||
if ( ff ) tempme.Results.ffloor = ff;
|
||||
tempme.Results.HitSector = CeilingSector;
|
||||
tempme.Results.HitType = TRACE_HitCeiling;
|
||||
|
|
@ -774,6 +785,12 @@ Class Demolitionist : PlayerPawn
|
|||
A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP);
|
||||
busted = true;
|
||||
raging.DoHitFX();
|
||||
if ( buttslam )
|
||||
{
|
||||
A_StartSound("demolitionist/buttslam",CHAN_DAMAGE,CHANF_OVERLAP,1.,.2);
|
||||
Spawn("SWWMItemFog",Vec3Offset(0,0,Height));
|
||||
A_QuakeEx(8,8,8,8,0,3000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollIntensity:1.);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !busted )
|
||||
|
|
@ -802,9 +819,12 @@ Class Demolitionist : PlayerPawn
|
|||
// check for wall collision
|
||||
FCheckPosition tm;
|
||||
Vector2 steppy = dir.xy*spd/8.;
|
||||
Vector3 oldpos = pos;
|
||||
bool oldthru = bTHRUACTORS;
|
||||
bTHRUACTORS = true;
|
||||
for ( int i=1; i<=8; i++ )
|
||||
{
|
||||
if ( (spd > 0) && !bumped && !CheckMove(Vec2Offset(steppy.x*i,steppy.y*i),PCM_DROPOFF|PCM_NOACTORS,tm) && BlockingLine )
|
||||
if ( (spd > 0) && !bumped && !TryMove(Vec2Offset(steppy.x,steppy.y),1,false,tm) && BlockingLine )
|
||||
{
|
||||
Vector3 wallnorm = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
|
||||
int lside = 1;
|
||||
|
|
@ -821,7 +841,13 @@ Class Demolitionist : PlayerPawn
|
|||
// see if we can bust it
|
||||
let tempme = new("LineTracer"); // gross hack to pass needed data
|
||||
int dmg = int(128+spd*20);
|
||||
if ( dir dot viewdir < -.3 ) dmg *= 3; // BUTTSLAM
|
||||
bool buttslam = false;
|
||||
// BUTTSLAM
|
||||
if ( dir dot viewdir < -.3 )
|
||||
{
|
||||
dmg *= 3;
|
||||
buttslam = true;
|
||||
}
|
||||
tempme.Results.HitLine = BlockingLine;
|
||||
tempme.Results.HitType = TRACE_HitWall;
|
||||
tempme.Results.Side = lside;
|
||||
|
|
@ -844,6 +870,12 @@ Class Demolitionist : PlayerPawn
|
|||
ps.special1 = int(15+spd*2.5);
|
||||
A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP);
|
||||
raging.DoHitFX();
|
||||
if ( buttslam )
|
||||
{
|
||||
A_StartSound("demolitionist/buttslam",CHAN_DAMAGE,CHANF_OVERLAP,1.,.2);
|
||||
Spawn("SWWMItemFog",Vec3Offset(dir.x*radius,dir.y*radius,(tempme.Results.Tier==TIER_UPPER)?Height:(tempme.Results.Tier==TIER_LOWER)?0:(Height/2)));
|
||||
A_QuakeEx(8,8,8,8,0,3000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollIntensity:1.);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -873,6 +905,8 @@ Class Demolitionist : PlayerPawn
|
|||
break;
|
||||
}
|
||||
}
|
||||
SetOrigin(oldpos,true);
|
||||
bTHRUACTORS = oldthru;
|
||||
}
|
||||
else if ( isboosting && (dashboost > 0.) )
|
||||
{
|
||||
|
|
@ -964,8 +998,8 @@ Class Demolitionist : PlayerPawn
|
|||
}
|
||||
override void MovePlayer()
|
||||
{
|
||||
if ( InStateSequence(CurState,FindState("Dash")) )
|
||||
player.cmd.forwardmove = player.cmd.sidemove = 0;
|
||||
bool isdashing = InStateSequence(CurState,FindState("Dash"));
|
||||
if ( isdashing ) player.cmd.forwardmove = player.cmd.sidemove = 0;
|
||||
if ( (waterlevel < 2) && (bFly || bFlyCheat) && !(player.cheats&CF_NOCLIP2) )
|
||||
{
|
||||
player.onground = false;
|
||||
|
|
@ -1049,7 +1083,7 @@ Class Demolitionist : PlayerPawn
|
|||
guidepitch *= .9;
|
||||
guideroll *= .9;
|
||||
// anchor to ground when going down steps
|
||||
if ( lastground && !player.onground && !bFly && !bFlyCheat && (waterlevel < 2) && (abs(pos.z-floorz) <= maxdropoffheight) && (player.jumptics == 0) && (vel.z < 0) )
|
||||
if ( lastground && !player.onground && !bFly && !bFlyCheat && (waterlevel < 2) && (abs(pos.z-floorz) <= maxdropoffheight) && (player.jumptics == 0) && (vel.z < 0) && !isdashing )
|
||||
{
|
||||
// test for gap crossing (i.e: climbing up platforms with holes between them)
|
||||
Vector3 storepos = pos;
|
||||
|
|
@ -1082,12 +1116,10 @@ Class Demolitionist : PlayerPawn
|
|||
if ( fm ) dodge += (fm>0)?X:-X;
|
||||
if ( sm ) dodge += (sm>0)?Y:-Y;
|
||||
if ( player.cmd.buttons&BT_CROUCH ) dodge = (0,0,-1); // death from above
|
||||
if ( player.onground ) dodge.z = max(0,dodge.z);
|
||||
if ( dodge == (0,0,0) ) dodge.xy = RotateVector((1,0),angle);
|
||||
if ( (waterlevel < 2) && !(bFly || bFlyCheat) )
|
||||
dodge.z += (player.cmd.buttons&BT_CROUCH)?-.05:.15;
|
||||
if ( !level.IsJumpingAllowed() ) dodge.z = min(0,dodge.z);
|
||||
if ( (dodge.length() > 0) && (dashcooldown <= 0) && (dashfuel > 20.) && player.cmd.buttons&BT_USER2 && (player.onground || level.IsJumpingAllowed()) && (gamestate == GS_LEVEL) )
|
||||
if ( player.onground ) dodge.z = max(0,dodge.z);
|
||||
if ( (dodge.length() > 0) && (dashcooldown <= 0) && (dashfuel > 20.) && player.cmd.buttons&BT_USER2 && (player.onground || level.IsJumpingAllowed() || (player.cmd.buttons&BT_CROUCH)) && (gamestate == GS_LEVEL) )
|
||||
{
|
||||
dashdir = dodge.unit();
|
||||
dashcooldown = 10;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue