diff --git a/language.def_base b/language.def_base index 391a3cece..9fc1da87a 100644 --- a/language.def_base +++ b/language.def_base @@ -945,6 +945,7 @@ SWWM_SHAMEFUL = "Humiliation"; SWWM_BUTTSLAM = "Buttslam"; SWWM_LOVED = "L\cg♥\c-VE"; SWWM_LOVED_ALT = "F\cg♥\c-CK NAZIS"; +SWWM_FROGGED = "CROAK"; // score messages SWWM_FINDSECRET = "\cf%s\cf found a secret. +%d\c-"; SWWM_FINDKEY = "\cf%s\cf got the %s\cf. +%d\c-"; diff --git a/language.es_base b/language.es_base index ccef8cff4..26f6b15af 100644 --- a/language.es_base +++ b/language.es_base @@ -879,6 +879,7 @@ SWWM_LEGPREFIX = "R"; SWWM_LTFORM = "\cf¡%s\cf Legendario se ha transformado!\c-"; SWWM_SHAMEFUL = "Humillación"; SWWM_BUTTSLAM = "Culazo"; +SWWM_FROGGED = "CROAC"; // score messages SWWM_FINDSECRET = "\cf%s\cf encontró un secreto. +%d\c-"; SWWM_FINDKEY = "\cf%s\cf obtuvo la %s\cf. +%d\c-"; diff --git a/language.version b/language.version index a159a2534..b120a060d 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r244 \cu(Sun 31 Jan 18:50:50 CET 2021)\c-"; -SWWM_SHORTVER="\cw0.9.11b-pre r244 \cu(2021-01-31 18:50:50)\c-"; +SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r245 \cu(Mon 1 Feb 13:38:23 CET 2021)\c-"; +SWWM_SHORTVER="\cw0.9.11b-pre r245 \cu(2021-02-01 13:38:23)\c-"; diff --git a/zscript/swwm_funstuff.zsc b/zscript/swwm_funstuff.zsc index 1a04acefa..307ee3e8e 100644 --- a/zscript/swwm_funstuff.zsc +++ b/zscript/swwm_funstuff.zsc @@ -213,6 +213,9 @@ Class FroggyChair : Actor { int cdown; bool carried; + bool wasonground; + double lastvelz; + Actor lasthit; Default { @@ -224,6 +227,7 @@ Class FroggyChair : Actor +NODAMAGE; +NOBLOOD; +INTERPOLATEANGLES; + +FORCEPAIN; } private void BeginCarry( Actor carrier ) { @@ -233,10 +237,10 @@ Class FroggyChair : Actor A_SetSize(32,32); // easier to deselect carried = true; bSOLID = false; - bSHOOTABLE = false; bNOGRAVITY = true; vel *= 0; - master = carrier; + tracer = master = carrier; + lasthit = null; } private void EndCarry() { @@ -245,9 +249,10 @@ Class FroggyChair : Actor A_SetSize(default.radius,default.height); carried = false; bSOLID = true; - bSHOOTABLE = true; bNOGRAVITY = false; master = null; + vel.z += vel.xy.length()*.2; + lasthit = null; } override void Tick() { @@ -261,22 +266,30 @@ Class FroggyChair : Actor } if ( carried ) { + prev = pos; if ( !master || (master.Health <= 0) ) EndCarry(); else { Vector3 tomove = master.Vec2OffsetZ(cos(master.angle)*40.,sin(master.angle)*40.,master.player.viewz-32.); Vector3 dirto = level.Vec3Diff(pos,tomove); - SetOrigin(level.Vec3Offset(pos,dirto*.3),true); + double intp = clamp(dirto.length()*.01,.3,.7); + SetOrigin(level.Vec3Offset(pos,dirto*intp),true); double magvel = dirto.length(); dirto /= magvel; - vel = dirto*min(20,magvel); + vel = dirto*min(50,magvel); double angleto = deltaangle(angle,AngleTo(master)); A_SetAngle(angle+angleto*.3,SPF_INTERPOLATE); } return; } + wasonground = ((pos.z <= floorz) || !TestMobjZ()); + lastvelz = vel.z; Super.Tick(); - if ( pos.z <= floorz ) vel.xy *= .9; // fast friction + if ( (pos.z <= floorz) || !TestMobjZ() ) + { + if ( !wasonground && (lastvelz < -1) ) A_StartSound("squeak",CHAN_BODY,CHANF_OVERLAP,clamp(-lastvelz*.05,0.,1.)); + vel.xy *= .9; // fast friction + } } override bool Used( Actor user ) { @@ -289,6 +302,51 @@ Class FroggyChair : Actor else BeginCarry(user); return true; } + override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle ) + { + if ( (damage > 0) && (special1 < level.maptime) ) + { + special1 = level.maptime+5; + A_StartSound("squeak",CHAN_VOICE); + } + return Super.DamageMobj(inflictor,source,damage,mod,flags,angle); + } + override bool CanCollideWith( Actor other, bool passive ) + { + Vector3 dir = vel; + double vsize = dir.length(); + // we need to compare Z height because wow thanks + Vector3 diff = level.Vec3Diff(pos,other.pos); + if ( (diff.z > height) || (diff.z < -other.height) ) return false; + if ( vsize > 1 ) + { + if ( other == lasthit ) + return false; + dir /= vsize; + if ( !passive && other.bSHOOTABLE && (!tracer || !other.IsFriend(tracer)) ) + { + lasthit = other; + SWWMUtility.DoKnockback(other,dir,5000*vsize); + Vector3 dirto = level.Vec3Diff(other.Vec3Offset(0,0,other.height/2),Vec3Offset(0,0,height)); + double lento = dirto.length(); + if ( lento <= double.epsilon ) + { + double ang = FRandom[DoBlast](0,360); + double pt = FRandom[DoBlast](-90,90); + dirto = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt)); + } + else dirto /= lento; + vel = (dirto+(0,0,.1))*vsize*.3; + Spawn("SWWMItemFog",pos); + other.DamageMobj(self,tracer,int(10*vsize),'Melee',DMG_THRUSTLESS); + A_StartSound("squeak",CHAN_WEAPON); + return false; + } + if ( other == tracer ) + return false; + } + return true; + } States { Spawn: diff --git a/zscript/swwm_handler.zsc b/zscript/swwm_handler.zsc index 8e5b2bd67..cce85336a 100644 --- a/zscript/swwm_handler.zsc +++ b/zscript/swwm_handler.zsc @@ -1610,6 +1610,17 @@ Class SWWMHandler : EventHandler scr.xcnt = ++ofs; } } + else if ( e.Inflictor is 'FroggyChair' ) + { + score += 800; + if ( scr ) + { + scr.xscore[ofs] = 0; + scr.xtcolor[ofs] = Font.CR_GREEN; + scr.xstr[ofs] = StringTable.Localize("$SWWM_FROGGED"); + scr.xcnt = ++ofs; + } + } if ( (e.Damage >= e.Thing.GetSpawnHealth()*2) || (((e.Thing.Health <= e.Thing.GetGibHealth()) || (src.bEXTREMEDEATH) || (e.Inflictor && e.Inflictor.bEXTREMEDEATH) || (e.DamageType == 'Extreme')) && !src.bNOEXTREMEDEATH && (!e.Inflictor || !e.Inflictor.bNOEXTREMEDEATH)) ) { score *= 2; @@ -2138,7 +2149,7 @@ Class SWWMHandler : EventHandler // cheat code handling String cht[] = { - "swwmlodsofemone", "swwmdeeplore", + "swwmlodsofemone", "swwmdeeplore", "swwmfroggygang", // SWWM Platinum cheats "swwmimstuck", "swwmarmojumbo", "swwmdangimhealthy", "swwmwarriorofzaemonath", "swwmpowerparp", "swwmcannotseemyhands", @@ -2150,7 +2161,7 @@ Class SWWMHandler : EventHandler }; String cmd[] = { - "swwmmoneycheat", "swwmlorecheat", + "swwmmoneycheat", "swwmlorecheat", "swwmfroggycheat", // SWWM Platinum cheats "swwmsafecheat", "swwmweaponcheat", "swwmhealcheat", "swwmynykroncheat", "swwmgravcheat", "swwminvischeat", @@ -3271,6 +3282,23 @@ Class SWWMHandler : EventHandler S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } + else if ( e.Name ~== "swwmfroggycheat" ) + { + if ( SWWMUtility.CheatsDisabled(e.Args[0]) ) + return; + if ( consoleplayer == e.Args[0] ) + { + Console.Printf("\cdHop!\c-"); + S_StartSound("misc/buyinv",CHAN_ITEM,CHANF_UI); + } + let mo = players[e.Args[0]].mo; + Actor f = Actor(ThinkerIterator.Create("FroggyChair").Next()); + if ( !f ) f = mo.Spawn("FroggyChair"); + f.SetOrigin(mo.Vec2OffsetZ(cos(mo.angle)*40.,sin(mo.angle)*40.,mo.player.viewz-32.),false); + f.A_SetAngle(f.AngleTo(mo)); + f.Spawn("SWWMItemFog",f.pos); + f.A_StartSound("bestsound",CHAN_ITEMEXTRA); + } } // stuff for hud diff --git a/zscript/swwm_inventory.zsc b/zscript/swwm_inventory.zsc index c697cfb44..60a462111 100644 --- a/zscript/swwm_inventory.zsc +++ b/zscript/swwm_inventory.zsc @@ -1505,7 +1505,8 @@ Class SWWMWeapon : Weapon abstract { // punching is not greeting/patting (that'd be weird) if ( (ut.uses[i].hitactor == self) || (ut.uses[i].hitactor is 'Demolitionist') - || (ut.uses[i].hitactor is 'HeadpatTracker') ) continue; + || (ut.uses[i].hitactor is 'HeadpatTracker') + || (ut.uses[i].hitactor is 'FroggyChair') ) continue; if ( ut.uses[i].hitactor.Used(self) ) break; } else if ( ut.uses[i].hitline && UseLineTracer.TangibleLine(ut.uses[i]) ) diff --git a/zscript/swwm_kbase.zsc b/zscript/swwm_kbase.zsc index f758d4436..d06402812 100644 --- a/zscript/swwm_kbase.zsc +++ b/zscript/swwm_kbase.zsc @@ -2495,6 +2495,7 @@ Class DemolitionistMenu : GenericMenu if ( stats.favweapon == -1 ) str = str.."N/A"; else if ( stats.wstats[stats.favweapon].w == 'SWWMWeapon' ) str = str..StringTable.Localize("$SWWM_YOURSELF"); else if ( stats.wstats[stats.favweapon].w == 'SWWMGesture' ) str = str..StringTable.Localize("$SWWM_DOKIDOKI"); + else if ( stats.wstats[stats.favweapon].w == 'SWWMItemGesture' ) str = str..StringTable.Localize("$T_FROGGY"); else if ( stats.wstats[stats.favweapon].w == 'Weapon' ) str = str..StringTable.Localize("$SWWM_GRAVKILL"); else { diff --git a/zscript/swwm_player.zsc b/zscript/swwm_player.zsc index b984f62fc..7c1a088a3 100644 --- a/zscript/swwm_player.zsc +++ b/zscript/swwm_player.zsc @@ -745,6 +745,8 @@ Class Demolitionist : PlayerPawn // add special check so corpses don't get stuck on top of monsters and players if ( encroached && encroached.bSOLID && (bSOLID || encroached.bACTLIKEBRIDGE) ) { + if ( (encroached is 'FroggyChair') && (encroached != oldencroached) ) + encroached.A_StartSound("squeak",CHAN_BODY,CHANF_OVERLAP); // try to follow movement (this method is awkward but works with monsters) if ( encroached == oldencroached ) { diff --git a/zscript/swwm_thinkers.zsc b/zscript/swwm_thinkers.zsc index a0d415f0a..c6255b0e2 100644 --- a/zscript/swwm_thinkers.zsc +++ b/zscript/swwm_thinkers.zsc @@ -214,7 +214,8 @@ Class SWWMStats : Thinker else if ( (inflictor is 'BigBiospark') || (inflictor is 'BiosparkBall') || (inflictor is 'BiosparkBeamImpact') || (inflictor is 'BiosparkComboImpact') || (inflictor is 'BiosparkComboImpactSub') || (inflictor is 'BiosparkBeam') || (inflictor is 'BiosparkArc') ) which = 'Sparkster'; else if ( (inflictor is 'CandyBeam') || (inflictor is 'CandyPop') || (inflictor is 'CandyMagArm') || (inflictor is 'CandyGunProj') || (inflictor is 'CandyMagProj') || (inflictor is 'CandyBulletImpact') ) which = 'CandyGun'; else if ( (inflictor is 'YnykronBeam') || (inflictor is 'YnykronImpact') || (inflictor is 'YnykronSingularity') || (inflictor is 'YnykronCloud') || (inflictor is 'YnykronVoidBeam') || (inflictor is 'YnykronLightningArc') || (inflictor is 'YnykronLightningImpact') ) which = 'Ynykron'; - else if ( (inflictor is 'Demolitionist') || (inflictor is 'DemolitionistShockwave') || (inflictor is 'DemolitionistRadiusShockwave') ) which = 'SWWMWeapon'; // hack to assume Demolitionist as weapon + else if ( (inflictor is 'Demolitionist') || (inflictor is 'DemolitionistShockwave') || (inflictor is 'DemolitionistRadiusShockwave') || (inflictor is 'SWWMGesture') + || (inflictor is 'SWWMItemGesture') ) which = 'SWWMWeapon'; // hack to assume Demolitionist as weapon else if ( inflictor is 'BigPunchSplash' ) { // guess from damagetype @@ -224,6 +225,8 @@ Class SWWMStats : Thinker which = 'SWWMGesture'; // others are just weapon melee, so keep the readyweapon } + else if ( inflictor is 'FroggyChair' ) + which = 'SWWMItemGesture'; // more gross hacks if ( damagetype == 'Falling' ) which = 'Weapon'; // the gross hacks continue if ( !which ) return;