diff --git a/cvarinfo.txt b/cvarinfo.txt index 2ecea0f20..4f860e6d2 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -213,6 +213,8 @@ nosave int swwm_achievement_acid = 0; nosave int swwm_achievement_salt = 0; nosave int swwm_achievement_nobuy = 0; nosave int swwm_achievement_mega = 0; +nosave int swwm_achievement_sanic = 0; +nosave int swwm_achievement_tele = 0; nosave int swwm_achievement_tetris = 0; nosave int swwm_achievement_pong = 0; nosave int swwm_achievement_snake = 0; diff --git a/language.def_base b/language.def_base index 0361781f2..d18164694 100644 --- a/language.def_base +++ b/language.def_base @@ -971,7 +971,11 @@ SWWM_ACHIEVEMENT_SALT_TXT = "Shoot 25 Saltshot rounds simultaneously"; SWWM_ACHIEVEMENT_NOBUY_TAG = "Sustained Savings"; SWWM_ACHIEVEMENT_NOBUY_TXT = "Don't spend any money for %d maps straight"; SWWM_ACHIEVEMENT_MEGA_TAG = "Megadeath"; -SWWM_ACHIEVEMENT_MEGA_TXT = "Kill a grand total of one million enemies."; +SWWM_ACHIEVEMENT_MEGA_TXT = "Kill a grand total of one million enemies"; +SWWM_ACHIEVEMENT_SANIC_TAG = "CHILLI DOGS"; +SWWM_ACHIEVEMENT_SANIC_TXT = "Reach a top speed of %d km/h."; +SWWM_ACHIEVEMENT_TELE_TAG = "A Soldier's Pastime"; +SWWM_ACHIEVEMENT_TELE_TXT = "Teleport some bread (a sandwich works too)"; SWWM_ACHIEVEMENT_TETRIS_TAG = "Tetromination"; SWWM_ACHIEVEMENT_TETRIS_TXT = "Complete a full game of Tetris"; SWWM_ACHIEVEMENT_PONG_TAG = "Danny Won, Yeah"; diff --git a/language.es_base b/language.es_base index 4c005f408..9dcafbae6 100644 --- a/language.es_base +++ b/language.es_base @@ -866,7 +866,11 @@ SWWM_ACHIEVEMENT_SALT_TXT = "Dispara 25 cartuchos de sal al mismo tiempo"; SWWM_ACHIEVEMENT_NOBUY_TAG = "Ahorro Máximo"; SWWM_ACHIEVEMENT_NOBUY_TXT = "No gastes dinero durante %d mapas seguidos"; SWWM_ACHIEVEMENT_MEGA_TAG = "Megamuerte"; -SWWM_ACHIEVEMENT_MEGA_TXT = "Mata un gran total de un millón de enemigos."; +SWWM_ACHIEVEMENT_MEGA_TXT = "Mata un gran total de un millón de enemigos"; +SWWM_ACHIEVEMENT_SANIC_TAG = "PERRITOS DE CHILE"; +SWWM_ACHIEVEMENT_SANIC_TXT = "Alcanza una velocidad punta de %d km/h"; +SWWM_ACHIEVEMENT_TELE_TAG = "Pasatiempo de Soldado"; +SWWM_ACHIEVEMENT_TELE_TXT = "Teletransporta pan (un sandwich también vale)"; SWWM_ACHIEVEMENT_TETRIS_TAG = "Tetrominación"; SWWM_ACHIEVEMENT_TETRIS_TXT = "Completa una partida entera de Tetris"; SWWM_ACHIEVEMENT_PONG_TAG = "Danny Ganó, Yeah"; diff --git a/language.version b/language.version index e98d1760f..557dbcb57 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r355 \cu(Sat 13 Mar 02:04:42 CET 2021)\c-"; -SWWM_SHORTVER="\cw0.9.11b-pre r355 \cu(2021-03-13 02:04:42)\c-"; +SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r357 \cu(Mon 15 Mar 22:04:08 CET 2021)\c-"; +SWWM_SHORTVER="\cw0.9.11b-pre r357 \cu(2021-03-15 22:04:08)\c-"; diff --git a/zscript/items/swwm_powerups.zsc b/zscript/items/swwm_powerups.zsc index f1a10805f..b96343597 100644 --- a/zscript/items/swwm_powerups.zsc +++ b/zscript/items/swwm_powerups.zsc @@ -61,12 +61,12 @@ Class GrilledCheeseSandwich : Inventory SWWMLoreLibrary.Add(Owner.player,"Nugget"); SWWMLoreLibrary.Add(Owner.player,"BlastSuit"); SWWMLoreLibrary.Add(Owner.player,"WarArmor"); + if ( Owner is 'Demolitionist' ) + Demolitionist(Owner).lastbump *= 1.2; if ( !extrasafe ) return; let s = Owner.FindInventory("GrilledCheeseSafeguard"); if ( !s ) Owner.GiveInventory("GrilledCheeseSafeguard",1); else Powerup(s).EffectTics = Powerup(s).default.EffectTics; - if ( Owner is 'Demolitionist' ) - Demolitionist(Owner).lastbump *= .87; } override bool Use( bool pickup ) { diff --git a/zscript/kbase/swwm_kbase.zsc b/zscript/kbase/swwm_kbase.zsc index 782f4acce..657012935 100644 --- a/zscript/kbase/swwm_kbase.zsc +++ b/zscript/kbase/swwm_kbase.zsc @@ -2502,7 +2502,7 @@ Class DemolitionistMenu : GenericMenu statlist.Push(str); str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFUEL"),stats.fuelusage/60.,StringTable.Localize("$SWWM_UNIT_LITER")); statlist.Push(str); - str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSPEED"),stats.topspeed*32000./(3600*GameTicRate),StringTable.Localize("$SWWM_UNIT_KPH")); + str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSPEED"),(stats.topspeed*3600.*GameTicRate)/32000.,StringTable.Localize("$SWWM_UNIT_KPH")); statlist.Push(str); thour = (stats.airtime/(3600*GameTicRate)); tmin = (stats.airtime/(60*GameTicRate))%60; diff --git a/zscript/swwm_player.zsc b/zscript/swwm_player.zsc index 54d1c2897..1e3bca50f 100644 --- a/zscript/swwm_player.zsc +++ b/zscript/swwm_player.zsc @@ -29,7 +29,7 @@ Class Demolitionist : PlayerPawn // for weapon bobbing stuff bool bumpdown; - double bumpvelz; + double bumpvelz, bumppitch; double oldangle, oldpitch; double oldlagangle, oldlagpitch, oldlagready; Vector3 oldlagvel; @@ -489,6 +489,7 @@ Class Demolitionist : PlayerPawn if ( !remove ) return; player.usedown = true; A_StartSound("bestsound",CHAN_ITEMEXTRA,CHANF_OVERLAP); + lastbump *= .97; if ( d.HitType == TRACE_HitWall ) { if ( d.Hit3DFloor ) @@ -853,6 +854,7 @@ Class Demolitionist : PlayerPawn // bump down weapon bumpdown = true; bumpvelz = -lastvelz; + bumppitch = min(-lastvelz/10.,20); if ( lastvelz < -25 ) { let s = Spawn("DemolitionistShockwave",pos); @@ -860,6 +862,8 @@ Class Demolitionist : PlayerPawn s.special1 = int(-lastvelz); A_Stop(); A_AlertMonsters(swwm_uncapalert?0:2500); + bumppitch = min(bumppitch+30,60); + lastbump *= 1.3; ReactionTime = 17; if ( player == players[consoleplayer] ) { @@ -869,12 +873,15 @@ Class Demolitionist : PlayerPawn } mystats.stompcount++; } + double newp = min(90,pitch+bumppitch); + bumppitch = newp-pitch; + A_SetPitch(newp,SPF_INTERPOLATE); if ( lastvelz < -10 ) A_StartSound("demolitionist/runstop",CHAN_FOOTSTEP,CHANF_OVERLAP); if ( (lastvelz < -gruntspeed) && (swwm_mutevoice < 4) && (health > 0) ) A_StartSound(String.Format("voice/%s/grunt",myvoice.GetString()),CHAN_DEMOVOICE,CHANF_OVERLAP); if ( lastvelz < -1 ) - A_Footstep(0,true,clamp(-lastvelz*0.05,0.0,1.0)); + A_Footstep(0,false,clamp(-lastvelz*0.05,0.0,1.0)); // bounce off slopes if ( pos.z <= floorz ) { @@ -945,8 +952,10 @@ Class Demolitionist : PlayerPawn if ( bumpdown ) { lagvel.z += bumpvelz*.2; + A_SetPitch(pitch-bumppitch/5.,SPF_INTERPOLATE); bumpvelz *= .8; - if ( bumpvelz < double.epsilon ) bumpdown = false; + bumppitch *= .8; + if ( (bumpvelz < double.epsilon) && (bumppitch < double.epsilon) ) bumpdown = false; } lastground = player.onground; lastvelz = prevvelz; @@ -962,7 +971,7 @@ Class Demolitionist : PlayerPawn if ( ((dashboost <= 0) || !(isdashing || (isboosting && player.cmd.buttons&BT_JUMP))) && IsActorPlayingSound(CHAN_JETPACK,"demolitionist/jet") ) A_StartSound("demolitionist/jetstop",CHAN_JETPACK); PainChance = isdashing?0:255; - if ( isdashing || (vel.length() > 50) ) + if ( isdashing || (vel.length() > 25) ) { Actor a; if ( isdashing && (dashboost > 0.) ) @@ -1023,7 +1032,7 @@ Class Demolitionist : PlayerPawn int flg = DMG_THRUSTLESS; if ( raging ) flg |= DMG_FOILINVUL; if ( !a.player && !a.bDONTBLAST ) a.bBLASTED = true; - int dmg = int(25+spd*2.5); + int dmg = int(10+spd*3.); bool buttslam = false; // BUTTSLAM if ( dir dot viewdir < -.3 ) @@ -1077,7 +1086,7 @@ Class Demolitionist : PlayerPawn { // see if we can bust it let tempme = new("LineTracer"); // gross hack to pass needed data - int dmg = int(25+spd*2.5); + int dmg = int(10+spd*3.); if ( raging ) dmg *= 8; bool buttslam = false; // BUTTSLAM @@ -1097,7 +1106,7 @@ Class Demolitionist : PlayerPawn let ps = Spawn("BigPunchSplash",Vec3Offset(0,0,Height)); ps.damagetype = buttslam?'Buttslam':'Dash'; ps.target = self; - ps.special1 = int(25+spd*2.5); + ps.special1 = int(10+spd*3.); raging.DoHitFX(); } A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP); @@ -1130,7 +1139,7 @@ Class Demolitionist : PlayerPawn let ps = Spawn("BigPunchSplash",Vec3Offset(0,0,Height)); ps.damagetype = (dir dot viewdir < -3.)?'Buttslam':'Dash'; ps.target = self; - ps.special1 = int(25+spd*2.5); + ps.special1 = int(10+spd*3.); raging.DoHitFX(); } } @@ -1169,7 +1178,7 @@ Class Demolitionist : PlayerPawn { // see if we can bust it let tempme = new("LineTracer"); // gross hack to pass needed data - int dmg = int(25+spd*2.5); + int dmg = int(10+spd*3.); if ( raging ) dmg *= 8; if ( buttslam ) dmg *= 3; tempme.Results.HitLine = BlockingLine; @@ -1193,7 +1202,7 @@ Class Demolitionist : PlayerPawn let ps = Spawn("BigPunchSplash",Vec3Offset(dir.x*radius,dir.y*radius,(tempme.Results.Tier==TIER_UPPER)?Height:(tempme.Results.Tier==TIER_LOWER)?0:(Height/2))); ps.damagetype = buttslam?'Buttslam':'Dash'; ps.target = self; - ps.special1 = int(30+spd*2.5); + ps.special1 = int(10+spd*3.); raging.DoHitFX(); } A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP); @@ -1224,7 +1233,7 @@ Class Demolitionist : PlayerPawn let ps = Spawn("BigPunchSplash",Vec3Offset(dir.x*radius,dir.y*radius,Height/2.)); ps.damagetype = (dir dot viewdir < -3.)?'Buttslam':'Dash'; ps.target = self; - ps.special1 = int(25+spd*2.5); + ps.special1 = int(10+spd*3.); raging.DoHitFX(); } // activate it @@ -1490,6 +1499,7 @@ Class Demolitionist : PlayerPawn player.jumptics = -1; SetStateLabel("Dash"); A_StartSound("demolitionist/jet",CHAN_JETPACK,CHANF_LOOP); + lastbump *= .95; mystats.dashcount++; } } @@ -1584,12 +1594,14 @@ Class Demolitionist : PlayerPawn if ( vel.z < 10. ) vel.z += jumpvelz+clamp(-pvelz*.6,0.,30.); vel.xy += walldir*20*Speed; + lastbump *= .95; } else if ( wallclimb ) { if ( vel.z < 10. ) vel.z += jumpvelz+clamp(-pvelz*.8,0.,30.); vel.xy -= walldir*5*Speed; + lastbump *= .97; } if ( jumpactor && jumpactor.bSHOOTABLE ) { @@ -1620,6 +1632,7 @@ Class Demolitionist : PlayerPawn if ( vel.z < 10. ) vel.z += jumpvelz+clamp(-pvelz*.4,0.,30.); A_StartSound("demolitionist/jet",CHAN_JETPACK,CHANF_LOOP); + lastbump *= .95; mystats.boostcount++; last_boost = level.maptime+1; } @@ -1628,6 +1641,8 @@ Class Demolitionist : PlayerPawn dashboost = 0.; if ( vel.z < 10. ) vel.z += jumpvelz*1.25; + if ( !walljump && !wallclimb ) + vel.xy += RotateVector((player.cmd.forwardmove,0),angle)/3000.; } SetStateLabel("Jump"); } @@ -1699,6 +1714,7 @@ Class Demolitionist : PlayerPawn A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,pitch:.7); A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,pitch:.4); } + lastbump *= 1.5; SWWMHandler.DoFlash(self,Color(255,255,255,255),10); SWWMHandler.DoFlash(self,Color(255,128,192,255),30); SWWMScoreObj.Spawn(default.health,Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Height/2),ST_Health); @@ -2027,21 +2043,27 @@ Class Demolitionist : PlayerPawn if ( !myvoice ) myvoice = CVar.GetCVar('swwm_voicetype',player); if ( lastdamage > 90 ) { + A_QuakeEx(3,3,3,9,0,8,"",QF_RELATIVE|QF_SCALEDOWN); A_StartSound("demolitionist/hipain",CHAN_VOICE); + lastbump *= 1.04; if ( !player || (player.mo != self) ) return; // voodoo dolls have no voice if ( swwm_mutevoice < 4 ) A_StartSound(String.Format("voice/%s/hipain",myvoice.GetString()),CHAN_DEMOVOICE,CHANF_OVERLAP); } else if ( lastdamage > 30 ) { + A_QuakeEx(2,2,2,6,0,8,"",QF_RELATIVE|QF_SCALEDOWN); A_StartSound("demolitionist/pain",CHAN_VOICE); + lastbump *= 1.02; if ( !player || (player.mo != self) ) return; // voodoo dolls have no voice if ( swwm_mutevoice < 4 ) A_StartSound(String.Format("voice/%s/pain",myvoice.GetString()),CHAN_DEMOVOICE,CHANF_OVERLAP); } else if ( lastdamage > 0 ) { + A_QuakeEx(1,1,1,3,0,8,"",QF_RELATIVE|QF_SCALEDOWN); A_StartSound("demolitionist/lopain",CHAN_VOICE); + lastbump *= 1.01; if ( !player || (player.mo != self) || (lastdamage < 5) ) return; // voodoo dolls have no voice if ( swwm_mutevoice < 4 ) A_StartSound(String.Format("voice/%s/lopain",myvoice.GetString()),CHAN_DEMOVOICE,CHANF_OVERLAP); @@ -2057,7 +2079,7 @@ Class Demolitionist : PlayerPawn Sound snd = "demolitionist/death"; if ( special1 < 10 ) snd = "demolitionist/wdeath"; - if ( health < 50 ) + if ( health < -50 ) snd = "demolitionist/xdeath"; A_StartSound(snd,CHAN_VOICE); if ( !player || (player.mo != self) ) return; // voodoo dolls have no voice @@ -2172,6 +2194,7 @@ Class Demolitionist : PlayerPawn A_StartSound("demolitionist/run",CHAN_FOOTSTEP,CHANF_OVERLAP,vol); let b = Spawn("InvisibleSplasher",level.Vec3Offset(pos,(RotateVector((0,yofs*.25*radius),angle),0))); b.A_CheckTerrain(); + vel.xy += RotateVector((player.cmd.forwardmove,0),angle)/2000.; } else { diff --git a/zscript/weapons/swwm_baseweapon_melee.zsc b/zscript/weapons/swwm_baseweapon_melee.zsc index bf3256269..cf73aaf73 100644 --- a/zscript/weapons/swwm_baseweapon_melee.zsc +++ b/zscript/weapons/swwm_baseweapon_melee.zsc @@ -360,6 +360,7 @@ extend Class SWWMWeapon if ( raging ) A_StartSound(bloodless?"pusher/althit":"pusher/altmeat",CHAN_WEAPON,CHANF_OVERLAP); else A_StartSound((hitsound!="")?hitsound:bloodless?"demolitionist/punch":"demolitionist/punchf",CHAN_WEAPON,CHANF_OVERLAP); A_AlertMonsters(swwm_uncapalert?0:300); + A_BumpFOV(.96); return true; } return false; @@ -437,6 +438,7 @@ extend Class SWWMWeapon } int quakin = raging?4:1; A_QuakeEx(quakin,quakin,quakin,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12*quakin); + A_BumpFOV(.98); A_StartSound(raging?"pusher/althit":(hitsound!="")?hitsound:"demolitionist/punch",CHAN_WEAPON,CHANF_OVERLAP); A_AlertMonsters(swwm_uncapalert?0:100); if ( raging ) raging.DoHitFX();