diff --git a/cvarinfo.txt b/cvarinfo.txt index ebaaaf866..1d48a1edb 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -55,6 +55,10 @@ 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 +server int swwm_maxblood = 1000; // max blood effects at any time +server int swwm_maxgibs = 200; // max gibs at any time +//server int swwm_maxcasings = 100; // TODO max casings and spent mags at any time +//server int swwm_maxdebris = 500; // TODO max chunks of debris at any time 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 user noarchive int swwm_cbtmeme = 0; // easter egg, hidden cvar diff --git a/language.def_menu b/language.def_menu index f12bc7d31..c6a12c8a7 100644 --- a/language.def_menu +++ b/language.def_menu @@ -117,6 +117,10 @@ SWWM_FUNTAGS = "Monster Renaming"; SWWM_SIMPLEFOG = "Simplified Teleport Fog"; SWWM_BIGTAGS = "Use Large Font for Names"; SWWM_INTERMUSIC = "Use Original Intermission Music"; +SWWM_MAXBLOOD = "Blood Limit"; +SWWM_MAXGIBS = "Gib Limit"; +SWWM_MAXCASINGS = "Casing Limit"; +SWWM_MAXDEBRIS = "Debris Limit"; 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."; @@ -176,6 +180,10 @@ TOOLTIP_SWWM_FUNTAGS = "Replaces the names of various vanilla monsters with funn 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."; TOOLTIP_SWWM_INTERMUSIC = "If enabled, intermission screens will use the original music from the current IWAD or map pack."; +TOOLTIP_SWWM_MAXBLOOD = "Caps the maximum amount of blood effects. Surpassing this limit will cause the excess to fade out."; +TOOLTIP_SWWM_MAXGIBS = "Caps the maximum amount of gibs. Surpassing this limit will cause the excess to fade out."; +TOOLTIP_SWWM_MAXCASINGS = "Caps the maximum amount of casings and spent magazines. Surpassing this limit will cause the excess to fade out."; +TOOLTIP_SWWM_MAXDEBRIS = "Caps the maximum amount of rubble from explosions and others. Surpassing this limit will cause the excess to fade out."; // knowledge base SWWM_COMINGSOON = "(coming soon)"; SWWM_MISSTAB = "Mission"; diff --git a/language.es_menu b/language.es_menu index 33ca4b3b1..a008dc82a 100644 --- a/language.es_menu +++ b/language.es_menu @@ -114,6 +114,10 @@ SWWM_FUNTAGS = "Renombrar Monstruos"; SWWM_SIMPLEFOG = "Efecto de Teletransporte Simple" SWWM_BIGTAGS = "Usar Fuente Grande para Nombres"; SWWM_INTERMUSIC = "Usar Música de Intermisión Original"; +SWWM_MAXBLOOD = "Límite de Sangre"; +SWWM_MAXGIBS = "Límite de Vísceras"; +SWWM_MAXCASINGS = "Límite de Casquillos"; +SWWM_MAXDEBRIS = "Límite de Escombros"; 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."; @@ -173,6 +177,10 @@ TOOLTIP_SWWM_FUNTAGS = "Reemplaza los nombres de monstruos vanilla por alternati 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."; TOOLTIP_SWWM_INTERMUSIC = "Al activar, las pantallas de intermisión usan la música original del IWAD o pack de mapas usado."; +TOOLTIP_SWWM_MAXBLOOD = "Limita la cantidad máxima de efectos de sangre. Sobrepasar este límite causará que el exceso se desvanezca."; +TOOLTIP_SWWM_MAXGIBS = "Limita la cantidad máxima de vísceras. Sobrepasar este límite causará que el exceso se desvanezca."; +TOOLTIP_SWWM_MAXCASINGS = "Limita la cantidad máxima de casquillos y cargadores usados. Sobrepasar este límite causará que el exceso se desvanezca."; +TOOLTIP_SWWM_MAXDEBRIS = "Limita la cantidad máxima de escombros por explosiones y otros. Sobrepasar este límite causará que el exceso se desvanezca."; // knowledge base SWWM_COMINGSOON = "(próximamente)"; SWWM_MISSTAB = "Misión"; diff --git a/language.version b/language.version index 0d9e2b563..4e2f58acf 100644 --- a/language.version +++ b/language.version @@ -1,2 +1,2 @@ [default] -SWWM_MODVER="\chSWWM \cwGZ\c- r515 (Tue 1 Sep 18:10:34 CEST 2020)"; +SWWM_MODVER="\chSWWM \cwGZ\c- r516 (Wed 2 Sep 00:49:19 CEST 2020)"; diff --git a/menudef.txt b/menudef.txt index 36d0bba85..d87d13026 100644 --- a/menudef.txt +++ b/menudef.txt @@ -34,6 +34,10 @@ OptionMenu "SWWMOptionMenu" StaticText " " StaticText "$SWWM_OTITLE", "Gold" Option "$SWWM_BLOOD", "swwm_blood", "YesNo" + Slider "$SWWM_MAXBLOOD", "swwm_maxblood", 0, 1000, 1, 0 + Slider "$SWWM_MAXGIBS", "swwm_maxgibs", 0, 1000, 1, 0 + //Slider "$SWWM_MAXCASINGS", "swwm_maxcasings", 0, 1000, 1, 0 + //Slider "$SWWM_MAXDEBRIS", "swwm_maxdebris", 0, 1000, 1, 0 Slider "$SWWM_FLASH", "swwm_flashstrength", 0.0, 1.0, 0.1, 1 Slider "$SWWM_HUDMARGIN", "swwm_hudmargin", 0, 40, 1, 0 Slider "$SWWM_MAXMSG", "swwm_maxshown", 1, 10, 1, 0 diff --git a/zscript/swwm_blod.zsc b/zscript/swwm_blod.zsc index 62ac74647..3d1fbcf63 100644 --- a/zscript/swwm_blod.zsc +++ b/zscript/swwm_blod.zsc @@ -106,8 +106,9 @@ Class mkBloodSpray : Actor // becomes a decal on crash Class mkBloodDrop : Actor { - int deadtimer; + bool killme; bool dead; + mkBloodDrop prevblod, nextblod; Default { @@ -131,6 +132,7 @@ Class mkBloodDrop : Actor { prev = pos; // for interpolation if ( isFrozen() ) return; + if ( killme ) A_FadeOut(.01); if ( dead ) { // do nothing but follow floor movement and eventually fade out @@ -140,8 +142,6 @@ Class mkBloodDrop : Actor UpdateWaterLevel(false); } if ( waterlevel > 0 ) A_FadeOut(); - deadtimer++; - if ( deadtimer > 350 ) A_FadeOut(.01); return; // we don't need to update states when we're dead } else @@ -232,11 +232,16 @@ Class mkBloodDrop : Actor override void PostBeginPlay() { Super.PostBeginPlay(); - deadtimer = Random[Blood](-20,20); + SWWMGoreHandler.QueueBlod(self); int jumps = Random[Blood](0,3); state dest = ResolveState("Spawn"); SetState(dest+jumps); } + override void OnDestroy() + { + SWWMGoreHandler.DeQueueBlod(self); + Super.OnDestroy(); + } States { Spawn: @@ -301,11 +306,12 @@ Class mkBloodSmoke2 : mkBloodSmoke // inspired by Lud's Universal Gibs Class mkFlyingGib : Actor { - int deadtimer; + bool killme; int lastbleed; color shadecol; bool bleeding; double rollvel; + mkFlyingGib prevmeat, nextmeat; override void PostBeginPlay() { @@ -320,13 +326,19 @@ Class mkFlyingGib : Actor vel += master.vel*1.5; CopyBloodColor(master); } - deadtimer = Random[Gibs](-20,20); rollvel = FRandom[Gibs](10,50)*RandomPick[Gibs](-1,1); scale *= FRandom[Gibs](.5,1.5); if ( master && master.bloodcolor ) shadecol = Color(master.bloodcolor.r/2,master.bloodcolor.g/2,master.bloodcolor.b/2); else shadecol = Color(80,0,0); bleeding = true; if ( Random[Blood](0,1) ) bXFlip = true; + SWWMGoreHandler.QueueMeat(self); + } + + override void OnDestroy() + { + SWWMGoreHandler.DeQueueMeat(self); + Super.OnDestroy(); } override void Tick() @@ -338,14 +350,20 @@ Class mkFlyingGib : Actor let s = Spawn("mkBloodSmoke",pos); s.SetShade(shadecol); } + if ( killme ) A_FadeOut(.01); if ( CurState == ResolveState("Death2") ) { - if ( vel.length() < .1 ) bleeding = false; - deadtimer++; - if ( deadtimer > 300 ) A_FadeOut(.01); + if ( vel.length() < .1 ) + bleeding = false; return; } roll += rollvel; + if ( waterlevel > 0 ) + { + rollvel *= .98; + vel *= .98; + if ( vel.length() < 10. ) A_FadeOut(.01); + } } override bool CanCollideWith(Actor other, bool passive) @@ -359,8 +377,8 @@ Class mkFlyingGib : Actor double ang; double pt; Vector3 dir; - if ( level.maptime <= invoker.lastbleed ) return; - invoker.lastbleed = level.maptime; + if ( invoker.lastbleed > level.maptime ) return; + invoker.lastbleed = level.maptime+5; for ( int i=0; i<8; i++ ) { let b = Spawn("mkBloodDrop",pos); @@ -566,6 +584,89 @@ Class CorpseFallTracker : Thinker Class SWWMGoreHandler : EventHandler { + mkBloodDrop blods, blods_end; + int blods_cnt; + mkFlyingGib meats, meats_end; + int meats_cnt; + + override void WorldLoaded( WorldEvent e ) + { + // recheck queues in case limits changed + while ( blods && (blods_cnt > swwm_maxblood) ) + DeQueueBlod(blods); + while ( meats && (meats_cnt > swwm_maxgibs) ) + DeQueueMeat(meats); + } + + static void QueueBlod( mkBloodDrop b ) + { + let hnd = SWWMGoreHandler(EventHandler.Find("SWWMGoreHandler")); + if ( !hnd ) return; + hnd.blods_cnt++; + if ( !hnd.blods ) + { + // this is the initial one + hnd.blods = b; + hnd.blods_end = b; + } + else + { + hnd.blods_end.nextblod = b; + b.prevblod = hnd.blods_end; + hnd.blods_end = b; + } + while ( hnd.blods && (hnd.blods_cnt > swwm_maxblood) ) + DeQueueBlod(hnd.blods); + } + static void DeQueueBlod( mkBloodDrop b ) + { + let hnd = SWWMGoreHandler(EventHandler.Find("SWWMGoreHandler")); + if ( !hnd || !hnd.blods ) return; + if ( (hnd.blods != b) && !b.prevblod && !b.nextblod ) return; + hnd.blods_cnt--; + if ( !b.prevblod ) hnd.blods = b.nextblod; + else b.prevblod.nextblod = b.nextblod; + if ( b == hnd.blods_end ) hnd.blods_end = b.prevblod; + if ( b.nextblod ) b.nextblod.prevblod = b.prevblod; + b.killme = true; + b.prevblod = null; + b.nextblod = null; + } + static void QueueMeat( mkFlyingGib m ) + { + let hnd = SWWMGoreHandler(EventHandler.Find("SWWMGoreHandler")); + if ( !hnd ) return; + hnd.meats_cnt++; + if ( !hnd.meats ) + { + // this is the initial one + hnd.meats = m; + hnd.meats_end = m; + } + else + { + hnd.meats_end.nextmeat = m; + m.prevmeat = hnd.meats_end; + hnd.meats_end = m; + } + while ( hnd.meats && (hnd.meats_cnt > swwm_maxgibs) ) + DeQueueMeat(hnd.meats); + } + static void DeQueueMeat( mkFlyingGib m ) + { + let hnd = SWWMGoreHandler(EventHandler.Find("SWWMGoreHandler")); + if ( !hnd || !hnd.meats ) return; + if ( (hnd.meats != m) && !m.prevmeat && !m.nextmeat ) return; + hnd.meats_cnt--; + if ( !m.prevmeat ) hnd.meats = m.nextmeat; + else m.prevmeat.nextmeat = m.nextmeat; + if ( m == hnd.meats_end ) hnd.meats_end = m.prevmeat; + if ( m.nextmeat ) m.nextmeat.prevmeat = m.prevmeat; + m.killme = true; + m.prevmeat = null; + m.nextmeat = null; + } + override void CheckReplacement( ReplaceEvent e ) { // only replace vanilla blood if no other gore mod is doing it