diff --git a/language.version b/language.version index 5868f9616..e37744bc8 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r1226 \cu(jue 12 jun 2025 23:11:50 CEST)\c-"; -SWWM_SHORTVER="\cw1.3pre r1226 \cu(2025-06-12 23:11:50)\c-"; +SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r1226 \cu(miƩ 25 jun 2025 14:30:48 CEST)\c-"; +SWWM_SHORTVER="\cw1.3pre r1226 \cu(2025-06-25 14:30:48)\c-"; diff --git a/zscript/compat/swwm_hdoom.zsc b/zscript/compat/swwm_hdoom.zsc index 392ac38ee..904e6dc56 100644 --- a/zscript/compat/swwm_hdoom.zsc +++ b/zscript/compat/swwm_hdoom.zsc @@ -3,25 +3,15 @@ // enjoy getting bonked, you pervy perv Class SWWMHDoomHandler : StaticEventHandler { + Mixin SWWMUIRandom; + int callout_len; ui int timer; ui TextureID bonker, bonk, bonked; bool detected; - ui int rss; ui Font mBigFont; - private ui int GetUIRandom() - { - return (rss = (rss<<1)*35447+(rss/87)); - } - - private ui double RandomShiver() - { - int sd = GetUIRandom(); - return ((abs(sd)%11)-5)*.1; - } - override void OnRegister() { if ( FindClass('HDoomPlayer','PlayerPawn') ) @@ -104,7 +94,7 @@ Class SWWMHDoomHandler : StaticEventHandler double oy = Screen.GetHeight()/2-4*scl; String str = "HORNY"; double alf = clamp(16-((timer%16)+e.FracTic)*2,0,16)/16.; - rss = MSTime()/10; + SetUIRandom(MSTime()/10); Vector2 ofs = (RandomShiver(),RandomShiver())*3.*scl*alf; Screen.DrawText(mBigFont,Font.CR_SAPPHIRE,ox-(mBigFont.StringWidth(str)*scl*2)/2+ofs.x,oy+8*scl+ofs.y,str,DTA_ScaleX,scl*2,DTA_ScaleY,scl*2); Screen.DrawText(mBigFont,Font.FindFontColor('MiniFlash'),ox-(mBigFont.StringWidth(str)*scl*2)/2+ofs.x,oy+8*scl+ofs.y,str,DTA_ScaleX,scl*2,DTA_ScaleY,scl*2,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alf); diff --git a/zscript/compat/swwm_shame.zsc b/zscript/compat/swwm_shame.zsc index f8bab78a1..b106ef068 100644 --- a/zscript/compat/swwm_shame.zsc +++ b/zscript/compat/swwm_shame.zsc @@ -18,6 +18,8 @@ // (except Black Edition, that one is just embarrassing) Class SWWMBrutalHandler : StaticEventHandler { + Mixin SWWMUIRandom; + ui int timer; ui Font fnt; ui TextureID eztex[7]; @@ -29,9 +31,6 @@ Class SWWMBrutalHandler : StaticEventHandler ui double ezlinesw[5]; ui int ezcolor[5]; bool detected; - ui int rss; - - const BOYTICRATE = 5; override void OnRegister() { @@ -150,23 +149,6 @@ Class SWWMBrutalHandler : StaticEventHandler for ( int i=0; i4)?gametic:klinger; + SetUIRandom((kcode>4)?gametic:klinger); for ( int i=0, pos=0; i 0 ) { - if ( !(gametic%3) ) talkframe = (talkframe==-1)?(abs(GetRandom())%5):-1; + if ( !(gametic%3) ) talkframe = (talkframe==-1)?(abs(GetUIRandom())%5):-1; talktics--; } else talkframe = -1; diff --git a/zscript/menu/swwm_title.zsc b/zscript/menu/swwm_title.zsc index 8f99bc8db..1cbb6393f 100644 --- a/zscript/menu/swwm_title.zsc +++ b/zscript/menu/swwm_title.zsc @@ -12,6 +12,8 @@ Struct TitleExplosion Class SWWMTitleStuff : EventHandler { + Mixin SWWMUIRandom; + ui bool bInitialized; ui TextureID tex[6]; ui TextureID letters[13]; @@ -24,22 +26,10 @@ Class SWWMTitleStuff : EventHandler ui TitleExplosion smk[64]; ui TextureID smk_frame[19]; ui int titletimer; - ui int rss; ui int stopinit_t; ui bool bFadeIn; ui Font mSmallFont, mBigFont; - private ui int GetUIRandom() - { - return (rss = (rss<<1)*35447+(rss/87)); - } - - private ui double RandomShiver() - { - int sd = GetUIRandom(); - return ((abs(sd)%11)-5)*.1; - } - private ui void TickExplosions() { if ( stopinit_t > 0 ) stopinit_t--; @@ -166,7 +156,7 @@ Class SWWMTitleStuff : EventHandler Screen.Dim(0xFF000000,1.,0,0,Screen.GetWidth(),Screen.GetHeight()); if ( titletimer < -20 ) { - rss = int(MSTime()*(GameTicRate/1000.)); + SetUIRandom(int(MSTime()*(GameTicRate/1000.))); Vector2 ofs = (RandomShiver(),RandomShiver())*clamp((80+titletimer+e.FracTic)/50.,0.,1.); tsize = TexMan.GetScaledSize(tex[3]); ofs *= tsize.y/10.; diff --git a/zscript/player/swwm_player_face.zsc b/zscript/player/swwm_player_face.zsc index 62b02b3e0..a73c5734f 100644 --- a/zscript/player/swwm_player_face.zsc +++ b/zscript/player/swwm_player_face.zsc @@ -1,6 +1,9 @@ // facial animation and cosmetics extend Class Demolitionist { + // dirt-cheap PRNG + // (make sure to keep algo in sync w/ swwm_utility_math.zsc ver if it + // ever changes) private int GetRandom() { return (rss = (rss<<1)*35447+(rss/87)); diff --git a/zscript/utility/swwm_utility_math.zsc b/zscript/utility/swwm_utility_math.zsc index 44130a4ee..98e3bc32f 100644 --- a/zscript/utility/swwm_utility_math.zsc +++ b/zscript/utility/swwm_utility_math.zsc @@ -7,6 +7,12 @@ Struct SWWMProjectionData int viewx, viewy, vieww, viewh; } +Struct SWWMFRNGState +{ + bool init; + uint x, y, z, w, v, d; +} + extend Class SWWMUtility { // cache some data that requires trig and quat math @@ -444,4 +450,101 @@ extend Class SWWMUtility double yscale = dist*len; return angle, pitch, yscale; } + + // XORWOW-based PRNG, the best and fastest we can really use in ZScript due to lack of 64-bit integers + private static uint XORWOW( SWWMFRNGState &rss ) + { + if ( !rss.init ) + { + rss.x = 123456789; + rss.y = 362436069; + rss.z = 521288629; + rss.w = 88675123; + rss.v = 5783321; + rss.d = 6615241; + rss.init = true; + } + uint t = rss.v; + uint s = rss.x; + rss.v = rss.w; + rss.w = rss.z; + rss.z = rss.y; + rss.y = s; + t ^= t>>2; + t ^= t<<1; + t ^= s^(s<<4); + rss.x = t; + rss.d += 362437; + return t+rss.d; + } + + // the public-callable functions + static uint FastRand( SWWMFRNGState &rss, uint mod = 0 ) + { + uint rslt = XORWOW(rss); + if ( mod ) return rslt%mod; + return rslt; + } + + static int FastRandRange( SWWMFRNGState &rss, int low, int high ) + { + if ( low >= high ) ThrowAbortException("FastRandomRange called with low >= high"); + uint range = uint(high-low); + int rslt = int(FastRand(rss,range)); + return low+rslt; + } + + static double FastFRand( SWWMFRNGState &rss ) + { + uint rslt = XORWOW(rss); + return rslt/double(uint.max); + } + + static Vector3 FastVRand( SWWMFRNGState &rss ) + { + double ang = FastFRand(rss)*360; + double pt = 90-FastFRand(rss)*180; + return (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt)); + } + + static Vector2 FastVRand2D( SWWMFRNGState &rss ) + { + double ang = FastFRand(rss)*360; + return (cos(ang),sin(ang)); + } +} + +// ultrafast PRNG for a bunch of UI stuff +// kept here to reduce duplication and to tweak the (very cheap) algo if needed +Mixin Class SWWMUIRandom +{ + private ui int rss; + + private ui void SetUIRandom( int seed ) + { + rss = seed; + } + + private ui int GetUIRandom() + { + return (rss = (rss<<1)*35447+(rss/87)); + } + + private ui double RandomShiver() + { + int sd = GetUIRandom(); + return ((abs(sd)%11)-5)*.1; + } + + private ui int RandomFall() + { + int sd = GetUIRandom(); + return ((abs(sd)%22)+10); + } + + private ui double RandomOffset() + { + int sd = GetUIRandom(); + return (abs(sd)&65535)/65535.; + } }