From 09cfb25c30d9dff9d24585d157957f88832eafc3 Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Sun, 16 Aug 2020 16:21:08 +0200 Subject: [PATCH] Implemented "Item Sense" feature. Rebalanced Hellblazer. Rebalanced Biospark Carbine combo. Hellblazer Crackshot sub-grenades home in on bounce, as was intended. Added zoom blur when dashing. Added option to use a big font for targetter labels. More robust ui<->play communication for Demolitionist menu actions. Increase fuel regen rate. Disable GZDoom's built-in back button on Demolitionist Menu, since in some cases it can render the top left of the menu inaccessible. --- TODO.md | 5 +- cvarinfo.txt | 2 + gldefs.pp | 8 ++ keyconf.txt | 3 + language.def_menu | 7 ++ language.es_menu | 7 ++ language.version | 2 +- menudef.txt | 2 + shaders/glsl/ZoomBlur.fp | 18 +++ zscript/swwm_blazeit.zsc | 41 +++++-- zscript/swwm_common.zsc | 159 +++++++++++++++++++++++++- zscript/swwm_hud.zsc | 91 ++++++++++++++- zscript/swwm_menu.zsc | 227 +++++++++++++++++++++++-------------- zscript/swwm_player.zsc | 25 +++- zscript/swwm_powerup.zsc | 5 +- zscript/swwm_sparkyboi.zsc | 34 +++--- 16 files changed, 512 insertions(+), 124 deletions(-) create mode 100644 shaders/glsl/ZoomBlur.fp diff --git a/TODO.md b/TODO.md index 6af51367e..e7b33e51f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,8 @@ Fundamental things before beta: - Ynykron Artifact altfire -Not so fundamental things during beta: +Not so fundamental things during first beta: - Extra Demolitionist animations (swimming, additional gestures) - - Item detection button (highlights nearby, visible items) - Dual wielding Explodium Gun - Quick grenade function (Explodium Mag) - Allow loading partial mags from spare bullets @@ -14,6 +13,7 @@ Not so fundamental things during beta: - Confetti gibs - Keen replacement (need ideas) - Achievements + - Extra Demolitionist Menu tabs (radio, pong minigame) - Collectables Extra things for later: @@ -24,7 +24,6 @@ Extra things for later: - A background with a bit more flair than just the fuzz shader - Some sort of flyby featuring the Demolitionist booting up, closeups of weapons/items etc. - Japanese localization - - Extra Demolitionist Menu tabs (radio, pong minigame) - Mod trailer video - Rewrite the entire Demolitionist Menu code from the ground up to be more easily extensible and adapt to any window size diff --git a/cvarinfo.txt b/cvarinfo.txt index f5a7d1d2e..2cae35d8f 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -53,6 +53,7 @@ user int swwm_barscale = 0; // target healthbar scaling (0 = use GZDoom scalin user int swwm_scrscale = 0; // score scaling (0 = use GZDoom scaling) user int swwm_numscale = 0; // damnum scaling (0 = use GZDoom scaling) user int swwm_poiscale = 0; // point of interest scaling (0 = use GZDoom scaling) +user int swwm_detscale = 0; // item sense scaling (0 = use GZDoom scaling) server bool swwm_blood = false; // custom blood/gibbing user bool swwm_fuzz = true; // allows toggling the fuzz shader on the demolitionist menus, useful if you're streaming/recording since it destroys the encoding quality user bool swwm_cbtpause = true; // wallbuster menu pauses the game @@ -73,3 +74,4 @@ user bool swwm_funtags = true; // replace vanilla monster names with silly one //server bool swwm_superfuel = false; // TODO enable unlimited fuel //server bool swwm_partytime = false; // TODO killed enemies burst into confetti server bool swwm_simplefog = false; // simplified teleport fogs (useful to speed up slaughterwads) +user bool swwm_bigtags = false; // use a bigger font for targeter tags diff --git a/gldefs.pp b/gldefs.pp index eb5158fde..18a126f0f 100644 --- a/gldefs.pp +++ b/gldefs.pp @@ -1,4 +1,12 @@ HardwareShader PostProcess beforebloom +{ + Name "ZoomBlur" + Shader "shaders/glsl/ZoomBlur.fp" 330 + Uniform float Str + Uniform float Fade + Uniform vec2 CenterSpot +} +HardwareShader PostProcess beforebloom { Name "SilverScope" Shader "shaders/glsl/SilverScope.fp" 330 diff --git a/keyconf.txt b/keyconf.txt index f26546db0..49a1ea06b 100644 --- a/keyconf.txt +++ b/keyconf.txt @@ -3,11 +3,14 @@ addmenukey "$SWWM_PRIMARYFIRE" "+attack" addmenukey "$SWWM_SECONDARYFIRE" "+altattack" addmenukey "$SWWM_RELOADFIRE" "+reload" addmenukey "$SWWM_ZOOMFIRE" "+zoom" +//addmenukey "$SWWM_EXTRAFIRE" "+user4" addmenukey "$SWWM_MELEE" "+user1" addmenukey "$SWWM_DASH" "+user2" +addmenukey "$SWWM_ITEMSENSE" "+user3" addmenukey "$SWWM_GESTURE1" "netevent swwmgesture 0" addmenukey "$SWWM_GESTURE2" "netevent swwmgesture 1" addmenukey "$SWWM_GESTURE3" "netevent swwmgesture 2" +//addmenukey "$SWWM_GESTURE4" "netevent swwmgesture 3" addmenukey "$SWWM_KBASE" "openmenu SWWMKnowledgeBaseMenu" defaultbind "j" "netevent swwmgesture 0" defaultbind "k" "netevent swwmgesture 1" diff --git a/language.def_menu b/language.def_menu index f439bed06..60fad0ee6 100644 --- a/language.def_menu +++ b/language.def_menu @@ -7,9 +7,12 @@ SWWM_RELOADFIRE = "Reload"; SWWM_ZOOMFIRE = "Tertiary Fire / Zoom"; SWWM_MELEE = "Melee Attack"; SWWM_DASH = "Dash"; +SWWM_ITEMSENSE = "Item Sense"; +SWWM_EXTRAFIRE = "Quaternary Fire"; SWWM_GESTURE1 = "Wave"; SWWM_GESTURE2 = "Thumbs Up"; SWWM_GESTURE3 = "Victory"; +SWWM_GESTURE4 = "Blow Kiss"; SWWM_KBASE = "Demolitionist Menu"; // mod menu SWWM_MTITLE = "SWWM GZ Options"; @@ -96,6 +99,7 @@ SWWM_BARSCALE = "Healthbar Scaling"; SWWM_NUMSCALE = "Number Scaling"; SWWM_SCRSCALE = "Score Scaling"; SWWM_POISCALE = "POI Scaling"; +SWWM_DETSCALE = "Item Sense Scaling"; SWWM_GZSCALE = "Use GZDoom Setting"; SWWM_BLOOD = "Enable Custom Blood"; SWWM_FUZZ = "Enable Animated Menu BG"; @@ -111,6 +115,7 @@ SWWM_MENUPAUSE = "Pause on Demolitionist Menu"; SWWM_FTITLE = "Fun Options"; SWWM_FUNTAGS = "Monster Renaming"; SWWM_SIMPLEFOG = "Simplified Teleport Fog"; +SWWM_BIGTAGS = "Use Large Font for Names"; TOOLTIP_SWWM_VOICETYPE = "Sets the voice pack for the player."; TOOLTIP_SWWM_MUTEVOICE = "Control what gets muted, if you'd rather have a more silent protagonist."; TOOLTIP_SWWM_FLASHSTRENGTH = "Screen flashes usually happen when firing some weapons, you can lower this if these effects are harmful for you."; @@ -154,6 +159,7 @@ TOOLTIP_SWWM_BARSCALE = "Scaling factor for targetter healthbars. Set to 0 to us TOOLTIP_SWWM_NUMSCALE = "Scaling factor for damage/healing numbers. Set to 0 to use GZDoom's own HUD scaling."; TOOLTIP_SWWM_SCRSCALE = "Scaling factor for score numbers. Set to 0 to use GZDoom's own HUD scaling."; TOOLTIP_SWWM_POISCALE = "Scaling factor for points of interest. Set to 0 to use GZDoom's own HUD scaling."; +TOOLTIP_SWWM_DETSCALE = "Scaling factor for sensed items. Set to 0 to use GZDoom's own HUD scaling."; TOOLTIP_SWWM_BLOOD = "Please note that these effects are kinda cheap and performance heavy. I'd honestly recommend Nashgore instead, it's better."; TOOLTIP_SWWM_FUZZ = "Toggling this off is recommended if you're recording/streaming as this effect can harm video quality."; TOOLTIP_SWWM_CBTPAUSE = "The game will pause while the Wallbuster reload menu is open (only in singleplayer)."; @@ -167,6 +173,7 @@ TOOLTIP_SWWM_YNYKRONALERT = "By default the Ynykron wakes all monsters in the ma TOOLTIP_SWWM_MENUPAUSE = "In single player, the Demolitionist Menu by default will pause everything. You can disable this if you want a more Souls-like experience (or if you want to have a read while actively waiting for some looooooooong elevator or other timed event)."; TOOLTIP_SWWM_FUNTAGS = "Replaces the names of various vanilla monsters with funny alternatives."; TOOLTIP_SWWM_SIMPLEFOG = "Replaces particle-based teleport fogs with simple sprites. Useful if they cause performance issues."; +TOOLTIP_SWWM_BIGTAGS = "By default name labels on healthbars are shown with a small, compact font. Enabling this will use a bigger one."; // knowledge base SWWM_COMINGSOON = "(coming soon)"; SWWM_MISSTAB = "Mission"; diff --git a/language.es_menu b/language.es_menu index 7b393e226..719d61d1d 100644 --- a/language.es_menu +++ b/language.es_menu @@ -7,9 +7,12 @@ SWWM_RELOADFIRE = "Recargar"; SWWM_ZOOMFIRE = "Fuego Terciario / Zoom"; SWWM_MELEE = "Ataque a Melé"; SWWM_DASH = "Esprintar"; +SWWM_ITEMSENSE = "Sensor de Items"; +SWWM_EXTRAFIRE = "Fuego Cuaternario"; SWWM_GESTURE1 = "Saludar"; SWWM_GESTURE2 = "Pulgar Arriba"; SWWM_GESTURE3 = "Victoria"; +SWWM_GESTURE4 = "Soplar Beso"; SWWM_KBASE = "Menú de Demolicionista"; // mod menu SWWM_MTITLE = "Opciones de SWWM GZ"; @@ -93,6 +96,7 @@ SWWM_BARSCALE = "Escala de Barras de Salud"; SWWM_NUMSCALE = "Escala de Números"; SWWM_SCRSCALE = "Escala de Puntuaciones"; SWWM_POISCALE = "Escala de Puntos de Interés"; +SWWM_DETSCALE = "Escala de Sensor de Items"; SWWM_GZSCALE = "Usar Opción de GZDoom"; SWWM_BLOOD = "Habilitar Sangre Personalizada"; SWWM_FUZZ = "Habilitar Fondo Animado de Menú"; @@ -108,6 +112,7 @@ SWWM_MENUPAUSE = "Pausar en Menú de Demolicionista"; SWWM_FTITLE = "Opciones Divertidas"; SWWM_FUNTAGS = "Renombrar Monstruos"; SWWM_SIMPLEFOG = "Efecto de Teletransporte Simple" +SWWM_BIGTAGS = "Usar Fuente Grande para Nombres"; TOOLTIP_SWWM_VOICETYPE = "Selecciona el pack de voz para el jugador."; TOOLTIP_SWWM_MUTEVOICE = "Controla lo que se mutea, si prefieres tener un protagonista más silencioso."; TOOLTIP_SWWM_FLASHSTRENGTH = "Los destellos en pantalla suelen ocurrir al disparar algunas armas, puedes reducirlo si este tipo de effectos te causan malestar."; @@ -151,6 +156,7 @@ TOOLTIP_SWWM_BARSCALE = "Factor de escalado para las barras de salud. Pon a 0 pa TOOLTIP_SWWM_NUMSCALE = "Factor de escalado para los números de daño/salud. Pon a 0 para usar el escalado de HUD de GZDoom."; TOOLTIP_SWWM_SCRSCALE = "Factor de escalado para los números de puntuación. Pon a 0 para usar el escalado de HUD de GZDoom."; TOOLTIP_SWWM_POISCALE = "Factor de escalado para los puntos de interés. Pon a 0 para usar el escalado de HUD de GZDoom."; +TOOLTIP_SWWM_DETSCALE = "Factor de escalado para los items detectados. Pon a 0 para usar el escalado de HUD de GZDoom."; TOOLTIP_SWWM_BLOOD = "Ten en cuenta que estos efectos son un poco cutres y bajan los frames. Sinceramente, recomendaría usar Nashgore, es mejor."; TOOLTIP_SWWM_FUZZ = "Desactivar ésto es recomendado si estás grabando o haciendo streaming, ya que este effecto puede dañar la calidad del vídeo."; TOOLTIP_SWWM_CBTPAUSE = "El juego será pausado mientras el menú de recarga de Wallbuster está abierto (sólo en modo de un jugador)."; @@ -164,6 +170,7 @@ TOOLTIP_SWWM_YNYKRONALERT = "Por defecto el Ynykron alerta a todos los monstruos TOOLTIP_SWWM_MENUPAUSE = "En modo de un jugador, el Menú de Demolicionista por defecto paus a todo. Puedes desactivar esto si quieres una experiencia más Souls-like (o si quieres leer un poco mientras esperas activamente algun ascensor leeeeeeento o algún otro evento temporizado)." TOOLTIP_SWWM_FUNTAGS = "Reemplaza los nombres de monstruos vanilla por alternativas graciosas."; TOOLTIP_SWWM_SIMPLEFOG = "Reemplaza los efectos de teletransporte basados en partículas con simples sprites. Útil si causan problemas de rendimiento."; +TOOLTIP_SWWM_BIGTAGS = "Por defecto los nombres de las barras de vida usan una fuente pequeña. Activando esta opción, se cambiará por una mayor."; // knowledge base SWWM_COMINGSOON = "(próximamente)"; SWWM_MISSTAB = "Misión"; diff --git a/language.version b/language.version index dbe15b2fd..7252bd919 100644 --- a/language.version +++ b/language.version @@ -1,2 +1,2 @@ [default] -SWWM_MODVER="\chSWWM \cwGZ\c- r484 (Sun 16 Aug 01:24:54 CEST 2020)"; +SWWM_MODVER="\chSWWM \cwGZ\c- r486 (Sun 16 Aug 16:27:44 CEST 2020)"; diff --git a/menudef.txt b/menudef.txt index f09091a3b..5d6a9600a 100644 --- a/menudef.txt +++ b/menudef.txt @@ -44,6 +44,7 @@ OptionMenu "SWWMOptionMenu" Slider "$SWWM_PICKLEN", "swwm_pickduration", 1, 30, 1, 0 Option "$SWWM_TARGET", "swwm_targeter", "YesNo" Option "$SWWM_TARGETTAG", "swwm_targettags", "YesNo" + Option "$SWWM_BIGTAGS", "swwm_bigtags", "YesNo" Option "$SWWM_BOSSBAR", "swwm_bosshealthbars", "YesNo" Option "$SWWM_DAMNUMS", "swwm_healthnums", "YesNo" Option "$SWWM_ACCDAMAGE", "swwm_accdamage", "YesNo" @@ -58,6 +59,7 @@ OptionMenu "SWWMOptionMenu" ScaleSlider "$SWWM_NUMSCALE", "swwm_numscale", 0, 8, 1, "$SWWM_GZSCALE" ScaleSlider "$SWWM_SCRSCALE", "swwm_scrscale", 0, 8, 1, "$SWWM_GZSCALE" ScaleSlider "$SWWM_POISCALE", "swwm_poiscale", 0, 8, 1, "$SWWM_GZSCALE" + ScaleSlider "$SWWM_DETSCALE", "swwm_detscale", 0, 8, 1, "$SWWM_GZSCALE" Option "$SWWM_SHADERS", "swwm_shaders", "YesNo" Option "$SWWM_INTERTYPE", "swwm_intertype", "SWWMInterType" Option "$SWWM_FUZZ", "swwm_fuzz", "YesNo" diff --git a/shaders/glsl/ZoomBlur.fp b/shaders/glsl/ZoomBlur.fp new file mode 100644 index 000000000..d022c09f8 --- /dev/null +++ b/shaders/glsl/ZoomBlur.fp @@ -0,0 +1,18 @@ +void main() +{ + vec2 p = CenterSpot-TexCoord; + vec4 res = vec4(0.); + vec2 d = (p/150.)*Str; + float w = 1.; + vec2 s = TexCoord; + float sum = 0.; + for ( int i=0; i<16; i++ ) + { + res += w*texture(InputTexture,s); + sum += w; + w *= .8; + s += d; + } + res /= sum; + FragColor = mix(texture(InputTexture,TexCoord),vec4(res.rgb,1.),Fade); +} diff --git a/zscript/swwm_blazeit.zsc b/zscript/swwm_blazeit.zsc index 8d2facf88..9e1e420b6 100644 --- a/zscript/swwm_blazeit.zsc +++ b/zscript/swwm_blazeit.zsc @@ -251,7 +251,7 @@ Class HellblazerMissile : Actor A_SetRenderStyle(1.0,STYLE_Add); A_SprayDecal("BigScorch",50); A_SetScale(4.5); - SWWMHandler.DoExplosion(self,500,320000,200,90); + SWWMHandler.DoExplosion(self,250,320000,200,90); A_NoGravity(); A_QuakeEx(5,5,5,15,0,1500,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollIntensity:.8); A_StopSound(CHAN_BODY); @@ -347,7 +347,7 @@ Class HellblazerCrackshot : HellblazerMissile A_SetRenderStyle(1.0,STYLE_Add); A_SprayDecal("BigScorch",50); A_SetScale(6.); - SWWMHandler.DoExplosion(self,500,320000,250,100); + SWWMHandler.DoExplosion(self,300,320000,250,100); A_NoGravity(); A_QuakeEx(6,6,6,20,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:800,rollIntensity:1.); A_StopSound(CHAN_BODY); @@ -416,7 +416,7 @@ Class HellblazerRavager : HellblazerMissile A_SetRenderStyle(1.0,STYLE_Add); A_SprayDecal("HugeScorch",50); A_SetScale(8.); - SWWMHandler.DoExplosion(self,800,320000,300,120); + SWWMHandler.DoExplosion(self,500,320000,300,120); A_NoGravity(); A_QuakeEx(6,6,6,30,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:800,rollIntensity:1.); A_StopSound(CHAN_BODY); @@ -494,7 +494,7 @@ Class HellblazerWarhead : HellblazerMissile A_SetRenderStyle(1.0,STYLE_Add); A_SprayDecal("WumboScorch",150); A_SetScale(7.); - SWWMHandler.DoExplosion(self,3000,600000,400,200); + SWWMHandler.DoExplosion(self,2000,600000,400,200); A_NoGravity(); A_QuakeEx(9,9,9,150,0,12000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:4000,rollIntensity:2.); A_StopSound(CHAN_BODY); @@ -647,7 +647,7 @@ Mixin Class HellblazerGrenade ReactionTime--; if ( ReactionTime <= 0 ) ExplodeMissile(); } - void A_HandleBounce() + virtual void A_HandleBounce() { Vector3 HitNormal = -vel.unit(); F3DFloor ff; @@ -759,7 +759,7 @@ Class HellblazerClusterMini : HellblazerMissile2 s.alpha *= .4; s.vel = .3*vel + (traildir+(FRandom[Hellblazer](-.4,.4),FRandom[Hellblazer](-.4,.4),FRandom[Hellblazer](-.4,.4))).unit()*FRandom[Hellblazer](1.,2.); } - if ( (deto > 1) && (special2 > 2) ) + if ( (deto > 1) && (special2 > 5) ) { ExplodeMissile(); return; @@ -769,7 +769,7 @@ Class HellblazerClusterMini : HellblazerMissile2 while ( bt.Next() ) { let t = bt.Thing; - if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),80) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue; + if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),60) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue; deto++; break; } @@ -782,7 +782,7 @@ Class HellblazerClusterMini : HellblazerMissile2 A_SetRenderStyle(1.0,STYLE_Add); A_SprayDecal("BigScorch",50); A_SetScale(2.5); - SWWMHandler.DoExplosion(self,100,200000,150,60); + SWWMHandler.DoExplosion(self,80,200000,150,60); A_NoGravity(); A_QuakeEx(4,4,4,12,0,1000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:400,rollIntensity:.6); A_StopSound(CHAN_BODY); @@ -856,6 +856,31 @@ Class HellblazerClusterMini : HellblazerMissile2 p.alpha *= 1-special1*.1; } } + override void A_HandleBounce() + { + Super.A_HandleBounce(); + if ( !bMISSILE ) return; + // try to steer towards a target + let bt = BlockThingsIterator.Create(self,800); + double closest = double.infinity; + Actor whomst = null; + while ( bt.Next() ) + { + let t = bt.Thing; + if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),800) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue; + double dist = Distance3D(t); + if ( dist > closest ) continue; + closest = dist; + whomst = t; + } + if ( !whomst ) return; + Vector3 dirto = level.Vec3Diff(pos,whomst.Vec3Offset(0,0,whomst.Height/2)); + dirto /= dirto.length(); + dirto.z += .3; + double spd = vel.length(); + vel /= spd; + vel = (vel*.3+dirto*.7)*spd; + } States { diff --git a/zscript/swwm_common.zsc b/zscript/swwm_common.zsc index b2cc0841f..3996ff456 100644 --- a/zscript/swwm_common.zsc +++ b/zscript/swwm_common.zsc @@ -1285,6 +1285,77 @@ Class SWWMInterest : Thinker } } +Class SWWMItemSense : Thinker +{ + Inventory item; + String tag; + int updated; + Demolitionist parent; + SWWMItemSense prev, next; + Vector3 pos; + + static SWWMItemSense Spawn( Demolitionist parent, Inventory item ) + { + if ( !parent || !item ) return null; + // only refresh the updated time if existing + for ( SWWMItemSense s=parent.itemsense; s; s=s.next ) + { + if ( s.item != item ) continue; + s.updated = level.maptime+35; + s.pos = item.Vec3Offset(0,0,16); + return s; + } + let i = new("SWWMItemSense"); + i.ChangeStatNum(STAT_USER); + i.item = item; + i.parent = parent; + i.updated = level.maptime+35; + i.UpdateTag(); + i.pos = item.Vec3Offset(0,0,16); + i.next = parent.itemsense; + if ( parent.itemsense ) parent.itemsense.prev = i; + parent.itemsense = i; + parent.itemsense_cnt++; + return i; + } + + void UpdateTag() + { + if ( !item ) return; + tag = item.GetTag(); + } + + override void OnDestroy() + { + if ( parent ) + { + parent.itemsense_cnt--; + if ( !prev ) + { + parent.itemsense = next; + if ( next ) next.prev = null; + } + else + { + prev.next = next; + if ( next ) next.prev = prev; + } + } + Super.OnDestroy(); + } + + override void Tick() + { + if ( !parent ) + { + Destroy(); + return; + } + // expire + if ( level.maptime > updated+70 ) Destroy(); + } +} + // enemy combat tracker Class SWWMCombatTracker : Thinker { @@ -2527,6 +2598,9 @@ Class SWWMHandler : EventHandler // heal/armor flashes need to be handled here so they don't stack transient int hflash[MAXPLAYERS], aflash[MAXPLAYERS]; + // for menu events + transient Array checklist; + transient CVar mutevoice, accdamage; transient ui CVar useshaders; transient CVar lang; @@ -2775,6 +2849,13 @@ Class SWWMHandler : EventHandler SWWMStats s; while ( s = SWWMStats(ti.Next()) ) s.AddLevelStats(); + PlayerInfo p = players[consoleplayer]; + Shader.SetEnabled(p,"ZoomBlur",false); + Shader.SetEnabled(p,"RagekitShader",false); + Shader.SetEnabled(p,"GhostShader",false); + Shader.SetEnabled(p,"InvinciShader",false); + Shader.SetEnabled(p,"Glitch",false); + Shader.SetEnabled(p,"Grain",false); } override void WorldLoaded( WorldEvent e ) @@ -2865,6 +2946,7 @@ Class SWWMHandler : EventHandler } } PlayerInfo p = players[consoleplayer]; + Shader.SetEnabled(p,"ZoomBlur",false); Shader.SetEnabled(p,"RagekitShader",false); Shader.SetEnabled(p,"GhostShader",false); Shader.SetEnabled(p,"InvinciShader",false); @@ -3778,6 +3860,7 @@ Class SWWMHandler : EventHandler if ( amt > maxgive ) amt = maxgive; } else if ( amt > def.MaxAmount ) amt = def.MaxAmount; + bool rslt = false; if ( (amt > 0) && players[e.Args[1]].mo.GiveInventory(item,amt,true) ) { players[e.Args[0]].mo.TakeInventory(item,amt); @@ -3787,6 +3870,17 @@ Class SWWMHandler : EventHandler // add messages if ( e.Args[0] == consoleplayer ) Console.Printf(StringTable.Localize("$SWWM_MSGSENT"),amt,def.GetTag(),players[e.Args[1]].GetUserName()); if ( e.Args[1] == consoleplayer ) Console.Printf(StringTable.Localize("$SWWM_MSGRECV"),players[e.Args[0]].GetUserName(),amt,def.GetTag()); + rslt = true; + } + if ( e.Args[0] == consoleplayer ) + { + let t = new("MenuTransaction"); + t.uid = e.Args[2]; + t.type = MenuTransaction.TT_ITEMSEND; + t.result = rslt; + t.used = item; + t.usedup = (players[e.Args[1]].mo.CountInv(item)<=0); + checklist.Push(t); } } else if ( e.Name.Left(17) ~== "swwmmarkloreread." ) @@ -3801,7 +3895,19 @@ Class SWWMHandler : EventHandler if ( !item ) return; let i = players[e.Args[0]].mo.FindInventory(item); if ( !i ) return; - players[e.Args[0]].mo.UseInventory(i); + bool rslt = players[e.Args[0]].mo.UseInventory(i); + if ( e.Args[0] == consoleplayer ) + { + let t = new("MenuTransaction"); + t.uid = e.Args[1]; + t.type = MenuTransaction.TT_ITEMUSE; + let w = (Class)(item); + if ( w ) t.result = (players[e.Args[0]].PendingWeapon==Weapon(i)); + else t.result = rslt; + t.used = item; + t.usedup = (!i||(i.Amount<=0)); + checklist.Push(t); + } } else if ( e.Name.Left(13) ~== "swwmdropitem." ) { @@ -3824,6 +3930,16 @@ Class SWWMHandler : EventHandler let drop = players[e.Args[0]].mo.DropInventory(i,amt); // add some random velocity so multiple drops don't get bunched together if ( drop ) drop.vel += (Actor.RotateVector((FRandom[Junk](-1.5,.5),FRandom[Junk](-2.5,2.5)),players[e.Args[0]].mo.angle),FRandom[Junk](2.,5.)); + if ( e.Args[0] == consoleplayer ) + { + let t = new("MenuTransaction"); + t.uid = e.Args[1]; + t.type = MenuTransaction.TT_ITEMDROP; + t.used = item; + t.result = drop; + t.usedup = (!i||(i.Amount<=0)); + checklist.Push(t); + } } else if ( e.Name ~== "swwmkoraxline" ) { @@ -3905,6 +4021,21 @@ Class SWWMHandler : EventHandler } cbt.waitreload = false; } + else if ( e.Name ~== "swwmcleartransaction" ) + { + if ( e.Args[1] != consoleplayer ) return; + for ( int i=0; i intpoints; Array scoreobjs; Array trackers; + Array senseitems; // the event handler, holding all sorts of stuff SWWMHandler hnd; @@ -27,7 +28,7 @@ Class SWWMStatusBar : BaseStatusBar SWWMVanillaBossHandler bosshnd; // client cvars - transient CVar safezone, maxchat[2], maxpick, chatduration, msgduration, pickduration, chatcol, teamcol, obitcol, critcol, pickcol, targetter, healthnums, scorenums, scorebonus, pois, targettag, lang, maxtarg, maxscore, maxdamns, hscale, bscale, nscale, sscale, iscale, midcol, midbcol, midduration; + transient CVar safezone, maxchat[2], maxpick, chatduration, msgduration, pickduration, chatcol, teamcol, obitcol, critcol, pickcol, targetter, healthnums, scorenums, scorebonus, pois, targettag, lang, maxtarg, maxscore, maxdamns, hscale, bscale, nscale, sscale, iscale, dscale, midcol, midbcol, midduration, bigtags; // shared stuff Vector2 ss, hs; @@ -35,6 +36,7 @@ Class SWWMStatusBar : BaseStatusBar Vector2 ssn, hsn; Vector2 sss, hss; Vector2 ssi, hsi; + Vector2 ssd, hsd; int margin; double FracTic; int chatopen; @@ -350,6 +352,34 @@ Class SWWMStatusBar : BaseStatusBar qsort_scoreobjs(a,p+1,h); } + // quicksort (item sense) + private int partition_itemsense( Array a, int l, int h ) + { + SWWMItemSense pv = a[h]; + int i = (l-1); + for ( int j=l; j<=(h-1); j++ ) + { + if ( CmpDist(pv.pos,a[j].pos) ) + { + i++; + SWWMItemSense tmp = a[j]; + a[j] = a[i]; + a[i] = tmp; + } + } + SWWMItemSense tmp = a[h]; + a[h] = a[i+1]; + a[i+1] = tmp; + return i+1; + } + private void qsort_itemsense( Array a, int l, int h ) + { + if ( l >= h ) return; + int p = partition_itemsense(a,l,h); + qsort_itemsense(a,l,p-1); + qsort_itemsense(a,p+1,h); + } + override void Tick() { Super.Tick(); @@ -507,6 +537,31 @@ Class SWWMStatusBar : BaseStatusBar scoreobjs.Resize(i); // sort by distance qsort_scoreobjs(scoreobjs,0,scoreobjs.Size()-1); + // check if player has item sense + let demo = Demolitionist(CPlayer.mo); + if ( demo && (demo.itemsense_cnt > 0) ) + { + if ( senseitems.Size() != demo.itemsense_cnt ) + senseitems.Resize(demo.itemsense_cnt); + total_sz = demo.itemsense_cnt; + i = 0; + for ( SWWMItemSense s=demo.itemsense; s && (i s.updated+35) ) continue; + senseitems[i++] = s; + } + // squeeze if some were discarded + if ( i != total_sz ) + senseitems.Resize(i); + // sort by distance + qsort_itemsense(senseitems,0,senseitems.Size()-1); + } // part of gross hackery to override nametag display if ( !ntags ) ntags = CVar.GetCVar('displaynametags',players[consoleplayer]); if ( CPlayer.inventorytics > 0 ) @@ -629,6 +684,29 @@ Class SWWMStatusBar : BaseStatusBar Screen.DrawText(fnt,Font.CR_WHITE,(vpos.x-hsi.x*fnt.StringWidth(tag)/2.)/hsi.x,(vpos.y+hsi.y*fnt.GetHeight()/2.)/hsi.y,tag,DTA_VirtualWidthF,ssi.x,DTA_VirtualHeightF,ssi.y,DTA_KeepRatio,true); } } + // sensed items + let demo = Demolitionist(CPlayer.mo); + if ( demo && (demo.itemsense_cnt > 0) ) + { + for ( int i=0; i used; + bool result, usedup; +} + Class SWWMKnowledgeBaseMenu : GenericMenu { enum EDemoTab @@ -61,11 +75,9 @@ Class SWWMKnowledgeBaseMenu : GenericMenu // color for chat CVar ccol, tcol; // for checks (duh) - Class lastuse; - int lastuseamt; - int checkuse; - int checkdrop; - int checksend; + Array checklist; + int lasttuid; + SWWMHandler hnd; // seeeeecret int kcode; // crimey clock stuff @@ -82,6 +94,11 @@ Class SWWMKnowledgeBaseMenu : GenericMenu return req; } + int GenTUID() + { + return lasttuid++; + } + override void Init( Menu parent ) { Super.Init(parent); @@ -89,6 +106,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu { // can't open this menu outside of the game or if dead // also can't if you're not the Demolitionist + EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer); Close(); return; } @@ -119,6 +137,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu stats = SWWMStats.Find(players[consoleplayer]); tmsg = "$SWWM_MAINCONTROLS"; tmsgtic = gametic+70; + lasttuid = Random[TUID](); + hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( gameinfo.gametype&GAME_Heretic ) { c_year = 2171; @@ -281,6 +301,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu { case MKEY_BACK: MenuSound("menu/democlose"); + EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer); Close(); return true; case MKEY_PAGEUP: @@ -568,12 +589,14 @@ Class SWWMKnowledgeBaseMenu : GenericMenu { // can't use this if ( invlist[sel0] is 'Ammo' ) return true; - lastuse = invlist[sel0].GetClass(); - lastuseamt = invlist[sel0].Amount; - // don't check weapons (or the lamp) - if ( !(invlist[sel0] is 'Weapon') && !(invlist[sel0] is 'SWWMLamp') ) - checkuse = gametic+(multiplayer?5:1); - EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer); + let t = new("MenuTransaction"); + t.uid = GenTUID(); + t.type = MenuTransaction.TT_ITEMUSE; + t.result = false; + // don't check weapons, always assume check succeeded + if ( invlist[sel0] is 'Weapon' ) t.result = true; + checklist.Push(t); + EventHandler.SendNetworkEvent(String.Format("swwmuseitem.%s",invlist[sel0].GetClassName()),consoleplayer,t.uid); } else if ( (curtab == TAB_STORE) && (storelist.Size() > 0) && (sel0 < storelist.Size()) ) { @@ -639,20 +662,24 @@ Class SWWMKnowledgeBaseMenu : GenericMenu else if ( sub && (sel0 != -1) && (invlist.Size() > 0) ) { // trade item - lastuse = invlist[sel1].GetClass(); - lastuseamt = invlist[sel1].Amount; - checksend = gametic+(multiplayer?5:1); - EventHandler.SendNetworkEvent(String.Format("swwmtrade.%s",invlist[sel1].GetClassName()),consoleplayer,playerlist[sel0]); + let t = new("MenuTransaction"); + t.uid = GenTUID(); + t.type = MenuTransaction.TT_ITEMSEND; + t.result = false; + checklist.Push(t); + EventHandler.SendNetworkEvent(String.Format("swwmtrade.%s",invlist[sel1].GetClassName()),consoleplayer,playerlist[sel0],t.uid); } } return true; case MKEY_CLEAR: if ( (curtab == TAB_INVENTORY) && (invlist.Size() > 0) ) { - lastuse = invlist[sel0].GetClass(); - lastuseamt = invlist[sel0].Amount; - checkdrop = gametic+(multiplayer?5:1); - EventHandler.SendNetworkEvent(String.Format("swwmdropitem.%s",invlist[sel0].GetClassName()),consoleplayer); + let t = new("MenuTransaction"); + t.uid = GenTUID(); + t.type = MenuTransaction.TT_ITEMDROP; + t.result = false; + checklist.Push(t); + EventHandler.SendNetworkEvent(String.Format("swwmdropitem.%s",invlist[sel0].GetClassName()),consoleplayer,t.uid); } else if ( (curtab == TAB_LIBRARY) && sub ) { @@ -764,7 +791,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu for ( int i=0; i 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); + if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag()); + else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); else str = invlist[i].GetTag(); len = fnt.StringWidth(str); if ( len > longest ) longest = len; @@ -808,7 +836,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu for ( int i=0; i 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); + if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag()); + else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); else str = invlist[i].GetTag(); len = fnt.StringWidth(str); if ( len > longest ) longest = len; @@ -836,7 +865,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu for ( int i=0; i 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); + if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag()); + else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); else str = invlist[i].GetTag(); len = fnt.StringWidth(str); if ( len > longest ) longest = len; @@ -880,7 +910,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu for ( int i=0; i 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); + if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag()); + else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); else str = invlist[i].GetTag(); len = fnt.StringWidth(str); if ( len > longest ) longest = len; @@ -1288,7 +1319,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu for ( int i=0; i 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); + if ( invlist[i] is 'Ammo' ) str = String.Format("(%d/%d) %s",invlist[i].Amount,invlist[i].MaxAmount,invlist[i].GetTag()); + else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); else str = invlist[i].GetTag(); len = fnt.StringWidth(str); if ( len > longest ) longest = len; @@ -1591,6 +1623,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if ( players[consoleplayer].Health <= 0 ) { // ded + EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer); Close(); return; } @@ -1633,6 +1666,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu } // re-sort by category qsort_inventory(invlist,0,invlist.Size()-1); + // crop selection + if ( sel0 >= invlist.Size() ) sel0 = max(0,invlist.Size()-1); } else if ( (curtab == TAB_STATS) && (sel1 == STAT_KILLS) ) { @@ -1649,6 +1684,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu let k = Key(players[consoleplayer].mo.FindInventory(Key.GetKeyType(i))); if ( k ) invlist.Push(k); } + // crop selection + if ( sel0 >= invlist.Size() ) sel0 = max(0,invlist.Size()-1); } else if ( curtab == TAB_STORE ) { @@ -1732,6 +1769,8 @@ Class SWWMKnowledgeBaseMenu : GenericMenu } // re-sort by category qsort_store(storelist,storeunits,0,storelist.Size()-1); + // crop selection + if ( sel0 >= storelist.Size() ) sel0 = max(0,storelist.Size()-1); } else if ( curtab == TAB_LIBRARY ) { @@ -1797,57 +1836,70 @@ Class SWWMKnowledgeBaseMenu : GenericMenu } // re-sort by category qsort_inventory(invlist,0,invlist.Size()-1); + // crop selection + if ( sel1 >= invlist.Size() ) sel1 = max(0,invlist.Size()-1); } } - // check if use succeeded - if ( checkuse && (gametic > checkuse) ) + // ui->play transaction checks + for ( int i=0; i= invlist.Size()) ) - sel0 = max(0,sel0-1); - } - } - // check if drop succeeded - if ( checkdrop && (gametic > checkdrop) ) - { - checkdrop = 0; - int amt = players[consoleplayer].mo.CountInv(lastuse); - if ( amt == lastuseamt ) - { - tmsg = StringTable.Localize("$SWWM_INVNDROP"); - tmsgtic = gametic+70; - MenuSound("menu/noinvuse"); - } - else if ( (amt == 0) && (sel0 >= invlist.Size()) ) - sel0 = max(0,sel0-1); - } - // check if trade succeeded - if ( checksend && (gametic > checksend) ) - { - checksend = 0; - int amt = players[consoleplayer].mo.CountInv(lastuse); - if ( amt == lastuseamt ) - { - tmsg = StringTable.Localize("$SWWM_TRADEFULL"); - tmsgtic = gametic+70; - MenuSound("menu/noinvuse"); - } - else - { - MenuSound("menu/demosel"); - if ( (amt == 0) && (sel1 >= invlist.Size()) ) - sel1 = max(0,sel1-1); + if ( hnd.checklist[j].uid != checklist[i].uid ) continue; + if ( checklist[i].type == MenuTransaction.TT_ITEMUSE ) + { + // check if use succeeded + if ( checklist[i].result || hnd.checklist[j].result ) + { + // only play use sound if game isn't frozen + if ( !multiplayer && (menuactive == Menu.On) ) + { + // if it's a weapon, play the select sound + let w = (Class)(hnd.checklist[j].used); + if ( w ) + { + // play if actually switching + if ( hnd.checklist[j].result ) MenuSound(GetDefaultByType(w).UpSound); + } + else MenuSound(GetDefaultByType(hnd.checklist[j].used).UseSound); + } + } + else + { + tmsg = StringTable.Localize("$SWWM_INVFAIL"); + tmsgtic = gametic+70; + MenuSound("menu/noinvuse"); + } + } + else if ( checklist[i].type == MenuTransaction.TT_ITEMDROP ) + { + // check if drop succeeded + if ( !hnd.checklist[j].result ) + { + tmsg = StringTable.Localize("$SWWM_INVNDROP"); + tmsgtic = gametic+70; + MenuSound("menu/noinvuse"); + } + } + else if ( checklist[i].type == MenuTransaction.TT_ITEMSEND ) + { + // check if trade succeeded + if ( !hnd.checklist[j].result ) + { + tmsg = StringTable.Localize("$SWWM_TRADEFULL"); + tmsgtic = gametic+70; + MenuSound("menu/noinvuse"); + } + else MenuSound("menu/demosel"); + } + EventHandler.SendNetworkEvent("swwmcleartransaction",checklist[i].uid,consoleplayer); + deleteme = true; + break; } + if ( !deleteme ) continue; + checklist.Delete(i); + i--; } } @@ -1893,6 +1945,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu if( (ikey[0] && (ev.keystring == mkey[0])) || (ikey[1] && (ev.keystring == mkey[1])) ) { MenuSound("menu/democlose"); + EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer); Close(); return true; } @@ -1933,41 +1986,41 @@ Class SWWMKnowledgeBaseMenu : GenericMenu break; case UIEvent.Type_LButtonDown: isrclick = false; - return Super.OnUIEvent(ev); + // copy over what base menus do for L click + // but ignore back button, since we don't use it + bool lres = MouseEvent(MOUSE_Click,ev.MouseX,ev.MouseY); + if ( lres ) SetCapture(true); + return lres; break; case UIEvent.Type_RButtonDown: isrclick = true; - // copy over what base menus do for L click - int y = ev.MouseY; - bool res = MouseEventBack(MOUSE_Click,ev.MouseX,y); - if ( res ) y = -1; - res |= MouseEvent(MOUSE_Click,ev.MouseX,y); - if ( res ) SetCapture(true); - return false; + // same as L click + bool rres = MouseEvent(MOUSE_Click,ev.MouseX,ev.MouseY); + if ( rres ) SetCapture(true); + return rres; break; + case UIEvent.Type_LButtonUp: case UIEvent.Type_RButtonUp: - // copy over what base menus do for L release + // copy over what base menus do for release + // but ignore back button, since we don't use it if ( mMouseCapture ) { SetCapture(false); - int y = ev.MouseY; - bool res = MouseEventBack(MOUSE_Release,ev.MouseX,y); - if ( res ) y = -1; - res |= MouseEvent(MOUSE_Release,ev.MouseX,y); + return MouseEvent(MOUSE_Release,ev.MouseX,ev.MouseY); } - return false; break; case UIEvent.Type_MouseMove: - // store coords + // store coords beforehand curmouse = (ev.MouseX,ev.MouseY); + if ( mMouseCapture || (m_use_mouse == 1) ) + return MouseEvent(MOUSE_Move,ev.MouseX,ev.MouseY); break; } - return Super.OnUIEvent(ev); + return false; } override void Drawer() { - Super.Drawer(); Font fnt = LangFont(TewiFont); String str; double hs; diff --git a/zscript/swwm_player.zsc b/zscript/swwm_player.zsc index 1f9b67aa6..aa95b4a58 100644 --- a/zscript/swwm_player.zsc +++ b/zscript/swwm_player.zsc @@ -46,10 +46,16 @@ Class Demolitionist : PlayerPawn int deadtimer; transient int revivefail; + transient int bumptic; + Actor selflight; Actor oldencroached; Vector3 oldencroachedpos; + SWWMItemSense itemsense; + int itemsense_cnt; + int lastsense; + Default { Speed 1; @@ -335,6 +341,21 @@ Class Demolitionist : PlayerPawn } fuelcooldown = max(20,fuelcooldown); } + void SenseItems() + { + if ( level.maptime < lastsense+5 ) + return; + lastsense = level.maptime; + let thesight = FindInventory("Omnisight"); + let bt = BlockThingsIterator.Create(self,1200); + while ( bt.Next() ) + { + let i = Inventory(bt.Thing); + if ( !i || i.bINVISIBLE || !i.bSPECIAL || i.Owner || !SWWMUtility.SphereIntersect(i,pos,thesight?1200:800) ) continue; + if ( !thesight && !CheckSight(i) ) continue; + SWWMItemSense.Spawn(self,i); + } + } void CheckUnderwaterAmb( bool restore = false ) { Vector3 headpos = Vec3Offset(0,0,player.viewheight); @@ -502,6 +523,7 @@ Class Demolitionist : PlayerPawn } else mystats.swimdist += traveldist; CheckUnderwaterAmb(); + if ( player.cmd.buttons&BT_USER3 ) SenseItems(); if ( vel.length() > mystats.topspeed ) mystats.topspeed = vel.length(); if ( !myvoice ) myvoice = CVar.GetCVar('swwm_voicetype',player); if ( !mute ) mute = CVar.GetCVar('swwm_mutevoice',player); @@ -593,7 +615,7 @@ Class Demolitionist : PlayerPawn dashcooldown = max(0,dashcooldown-1); boostcooldown = max(0,boostcooldown-1); if ( fuelcooldown <= 0 ) - dashfuel = min(240.,dashfuel+max(dashfuel*.01,.05)); + dashfuel = min(240.,dashfuel+max(dashfuel*.015,.1)); if ( (dashboost > 0.) && (InStateSequence(CurState,FindState("Dash")) || (InStateSequence(CurState,FindState("Jump")) && player.cmd.buttons&BT_JUMP)) ) dashsnd = true; else @@ -634,6 +656,7 @@ Class Demolitionist : PlayerPawn A_QuakeEx(4,4,4,10,0,128,"",QF_RELATIVE|QF_SCALEDOWN); A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP); a.A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP); + bumptic = gametic+int(5+spd/4.); if ( (diff.z < a.height) && (lastvelz >= -25) && (a.bDONTTHRUST || (a.Mass >= Mass*1.5)) ) { if ( bumped ) continue; diff --git a/zscript/swwm_powerup.zsc b/zscript/swwm_powerup.zsc index 67e18dd31..02e0840d4 100644 --- a/zscript/swwm_powerup.zsc +++ b/zscript/swwm_powerup.zsc @@ -236,7 +236,7 @@ Class GhostArtifactX : Actor +NOCLIP; +DONTSPLASH; +NOINTERACTION; - Radius 0.1; + Radius .1; Height 0; +FLOATBOB; FloatBobStrength 0.25; @@ -249,7 +249,8 @@ Class GhostArtifactX : Actor Destroy(); return; } - Warp(target,flags:WARPF_COPYINTERPOLATION|WARPF_NOCHECKPOSITION); + Warp(target,flags:WARPF_INTERPOLATE|WARPF_NOCHECKPOSITION); + FloatBobPhase = target.FloatBobPhase; bInvisible = target.bInvisible||!target.InStateSequence(target.CurState,target.FindState("Spawn")); } States diff --git a/zscript/swwm_sparkyboi.zsc b/zscript/swwm_sparkyboi.zsc index e8a825f70..3bf3fc4f1 100644 --- a/zscript/swwm_sparkyboi.zsc +++ b/zscript/swwm_sparkyboi.zsc @@ -887,7 +887,7 @@ Class BiosparkComboImpact : Actor { Super.PostBeginPlay(); A_AlertMonsters(6000); - SWWMHandler.DoExplosion(self,bAMBUSH?(1600+Args[0]*100):1500,480000,bAMBUSH?1200:700,bAMBUSH?900:400); + SWWMHandler.DoExplosion(self,bAMBUSH?(700+Args[0]*100):300,bAMBUSH?480000:200000,bAMBUSH?800:400,bAMBUSH?400:200); A_QuakeEx(9,9,9,25,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:600,rollIntensity:1.5); A_StartSound("biospark/bighit",CHAN_ITEM,attenuation:.4); A_StartSound("biospark/bighit",CHAN_WEAPON,attenuation:.3); @@ -930,8 +930,8 @@ Class BiosparkComboImpact : Actor s.target = target; s.angle = ang; s.pitch = pt; - s.ReactionTime += Random[Sparkster](0,10); - if ( bAMBUSH ) s.ReactionTime += 4+Args[0]*4; + s.ReactionTime += Random[Sparkster](0,5); + if ( bAMBUSH ) s.ReactionTime += 8+Args[0]*4; } if ( bAMBUSH ) { @@ -950,18 +950,13 @@ Class BiosparkComboImpact : Actor } void A_SparkSubExpl() { - double mx = bAMBUSH?30.:20.; + double mx = bAMBUSH?40.:30.; special1++; if ( special1 > mx ) return; double factor = (mx-special1)/mx; double invfct = 1.-factor; - if ( bAMBUSH ) - { - factor *= 1.5; - invfct *= 1.5; - } - SWWMHandler.DoExplosion(self,(1500+Args[0]*50)*factor,0.,600*invfct); - SWWMHandler.DoExplosion(self,0.,-10000*factor,800*invfct); + SWWMHandler.DoExplosion(self,(bAMBUSH?(500+Args[0]*50):200)*factor,0.,(bAMBUSH?900.:300.)*invfct); + SWWMHandler.DoExplosion(self,0.,-12000*factor,(bAMBUSH?1500:500)*invfct); int numpt = int(Random[ExploS](8,16)*factor); for ( int i=0; i 30) || !(special2%2) ) return; - int numpt = Random[Sparkster](0,30-special2); + int mx = bAMBUSH?40:30; + if ( (special2 > mx) || !(special2%2) ) return; + int numpt = Random[Sparkster](0,mx-special2); double ang, pt; - double mul = bAMBUSH?8:4; + double mul = bAMBUSH?8:3; for ( int i=0; i