// event handlers and whatnot // save version holder Class SWWMSaveVerData : Thinker { String ver; } // Static handler responsible for some special stuff Class SWWMStaticHandler : StaticEventHandler { // crash handler ui bool wasinmap; ui int timer; // versioning bool tainted; String taintver; bool mptaint[MAXPLAYERS]; bool mprecv[MAXPLAYERS]; String mpver[MAXPLAYERS]; int checktic; ui bool mpsent, checked; override void NewGame() { // set save version every new session let svd = new("SWWMSaveVerData"); svd.ChangeStatNum(Thinker.STAT_STATIC); svd.ver = StringTable.Localize("$SWWM_SHORTVER"); } override void WorldLoaded( WorldEvent e ) { // save version checker if ( !e.IsSaveGame ) return; checktic = gametic+5; let ti = ThinkerIterator.Create("SWWMSaveVerData",Thinker.STAT_STATIC); let svd = SWWMSaveVerData(ti.Next()); if ( !svd ) { tainted = true; taintver = "\cg(no version info)\c-"; return; } String cver = StringTable.Localize("$SWWM_SHORTVER"); if ( svd.ver != cver ) { tainted = true; taintver = svd.ver; } } override void OnRegister() { // preload various fonts Font.GetFont('k6x8'); Font.GetFont('k6x8Shaded'); Font.GetFont('k6x8ShadedInverse'); Font.GetFont('Miniwi'); Font.GetFont('MiniwiShaded'); Font.GetFont('MiniwiShadedInverse'); Font.GetFont('MPlus'); Font.GetFont('MPlusShaded'); Font.GetFont('MPlusShadedInverse'); Font.GetFont('Tewi'); Font.GetFont('TewiShaded'); Font.GetFont('TewiShadedInverse'); Font.GetFont('SWWMBigFont'); } override void ConsoleProcess( ConsoleEvent e ) { static const Name mmvars[] = { 'swwm_mm_backcolor', 'swwm_mm_cdwallcolor', 'swwm_mm_efwallcolor', 'swwm_mm_fdwallcolor', 'swwm_mm_gridcolor', 'swwm_mm_interlevelcolor', 'swwm_mm_intralevelcolor', 'swwm_mm_lockedcolor', 'swwm_mm_notseencolor', 'swwm_mm_portalcolor', 'swwm_mm_secretsectorcolor', 'swwm_mm_secretwallcolor', 'swwm_mm_specialwallcolor', 'swwm_mm_thingcolor', 'swwm_mm_thingcolor_citem', 'swwm_mm_thingcolor_friend', 'swwm_mm_thingcolor_item', 'swwm_mm_thingcolor_monster', 'swwm_mm_thingcolor_ncmonster', 'swwm_mm_thingcolor_shootable', 'swwm_mm_thingcolor_vipitem', 'swwm_mm_tswallcolor', 'swwm_mm_unexploredsecretcolor', 'swwm_mm_wallcolor', 'swwm_mm_xhaircolor', 'swwm_mm_yourcolor' }; if ( e.Name ~== "swwmresetmmcolors" ) { for ( int i=0; i 0)) ) { wasinmap = false; if ( timer == 1 ) { Console.Printf("\cfOopsie Woopsie!\c-"); let hnd = SWWMBrutalHandler(StaticEventHandler.Find("SWWMBrutalHandler")); if ( hnd && hnd.detected ) { S_StartSound("crash/glass",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE); S_StartSound("crash/glass",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE); } else S_StartSound("crash/crash",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE); } else if ( timer == 70 ) { Console.Printf("\cfLooks like GZDoom made a fucky wucky! owo\c-"); S_StartSound("crash/curb",CHAN_YOUDONEFUCKEDUP,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE); } else if ( timer == 140 ) { let hnd = SWWMBrutalHandler(StaticEventHandler.Find("SWWMBrutalHandler")); if ( hnd && hnd.detected ) Console.Printf("\cfDon't blame me. Shouldn't have tried running this with Brutal Doom.\c-"); else Console.Printf("\cfIf you didn't trigger it manually, it's best if you take a screenshot and show it to Marisa.\c-"); Console.Printf("\cfLoaded Version:\n \cj%s\c-",StringTable.Localize("$SWWM_SHORTVER")); if ( tainted ) Console.Printf("\cfSavegame Version:\n \cj%s\c-",taintver); } timer++; } } } // fuck Class DontDuplicate : Inventory {} Class DontDuplicate2 : Inventory {} Class HOLYCOWIMTOTALLYGOINGSOFASTOHFUCK : Inventory { override void DoEffect() { Super.DoEffect(); if ( !Owner || (Owner.Health <= 0) ) return; if ( (Owner.tics > 1) && (Owner.tics > max(1,Owner.CurState.tics/2)) ) Owner.tics = max(1,Owner.CurState.tics/2); } } // Handler responsible for item replacements and whatever else Class SWWMHandler : EventHandler { transient String oneliner, onelinersnd; transient int onelinertic, onelinerspan, onelinerlevel; transient int lastlock, lastcombat; transient Array combatactors; transient Array combattics; transient int highesttic; transient Array flashes; transient Array lastlines; transient int lastpickuptic[MAXPLAYERS]; SWWMCombatTracker trackers; SWWMScoreObj scorenums, damnums; SWWMInterest intpoints; SWWMSimpleTracker strackers; int trackers_cnt, scorenums_cnt, damnums_cnt, intpoints_cnt, strackers_cnt; bool tookdamage[MAXPLAYERS]; int spreecount[MAXPLAYERS]; int lastkill[MAXPLAYERS]; int multilevel[MAXPLAYERS]; int lastitemcount[MAXPLAYERS]; bool mnotify; bool allkills, allitems, allsecrets; bool mapclear; int mapclearagain, restartmus; String lastmus; int lastorder; bool lastloop; // for custom cheats transient ui int kcode, klinger; transient ui String kstr, klingerstr; transient ui bool kfail; transient ui int rss; // 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 String curlang; transient bool curfuntags; transient int slotstrictwarn; // optimization OnFire fires; int fires_cnt; // junk SWWMCasing casings, casings_end; int casings_cnt, oldmaxcasings; SWWMChip chips, chips_end; int chips_cnt, oldmaxdebris; // gore mkBloodDrop blods, blods_end; int blods_cnt, oldmaxblood; mkFlyingGib meats, meats_end; int meats_cnt, oldmaxgibs; // prevents revived monsters from spawning in more golden shells Array alreadygold; // attempt to optimize Ynykron singularity suction Array suckableactors; // vanilla boss stuff String bosstag; Array bossactors; Actor bossbrainactor; Actor bossviewactor; TextureID facetex[5]; bool initialized; ui bool ui_initialized; ui TextureID bbar_f, bbar_r, bbar_d; ui double bossalpha; ui DynamicValueInterpolator ihealth, ihealthr; ui int thealth, hmax; ui int oldhealth[30]; ui int cummdamage, lastcummtic; // please do not misread bool nugflip; // h/a nugget flip-flop spawn counter // stuff to reduce worldthingspawned overhead int bossmap; int iwantdie; int indoomvacation; bool hasdrlamonsters; // for minimap Array ffsectors; enum EVanillaMap { MAP_NONE, MAP_DE1M8, MAP_DE2M8, MAP_DE3M8, MAP_DE4M8, MAP_HE1M8_HE4M8, MAP_HE2M8_HE5M8, MAP_HE3M8, MAP_DMAP07, MAP_DMAP30, MAP_HMAP12, MAP_HMAP23_HMAP27_HMAP48_HMAP55, MAP_HMAP36, MAP_HMAP37, MAP_HMAP38, MAP_HMAP40, MAP_HMAP60, MAP_EVMAP30 // eviternity }; private int WhichVanillaBossMap() { String mapsum = level.GetChecksum(); if ( (mapsum ~== "94500F4B006B316FE03AC46865AEABF8") || (mapsum ~== "97079958C7E89C1908890730B8B9FEB7") || (mapsum ~== "058FB092EA1B70DA1E3CBF501C4A91A1") ) return MAP_DE1M8; if ( mapsum ~== "EFFE91DF41AD41F6973C06F0AD67DDB9" ) return MAP_DE2M8; if ( mapsum ~== "EF128313112110ED6C1549AF96AF26C9" ) return MAP_DE3M8; if ( mapsum ~== "2DC939E508AB8EB68AF79D5B60568711" ) return MAP_DE4M8; if ( (mapsum ~== "27639D04F8090D57A47D354992435893") || (mapsum ~== "30D1480A6D4F3A3153739D4CCF659C4E") ) return MAP_HE1M8_HE4M8; if ( (mapsum ~== "5158C22A0F30CE5E558FD2A05D67685E") || (mapsum ~== "85AC7D20D18F9BC49B9696CC2E67F029") ) return MAP_HE2M8_HE5M8; if ( mapsum ~== "4719C2C71EF28F52310B889DD5A9778B" ) return MAP_HE3M8; if ( mapsum ~== "291F24417FB3DD411339AE82EF9B3597" ) return MAP_DMAP07; if ( mapsum ~== "5EECD88F4491F516D590CE4BBF45F532" ) return MAP_DMAP30; if ( (mapsum ~== "89C4CD26EF05E2577B10CAFE56226662") || (mapsum ~== "441BF111747671066A10A146C03EEFC4") || (mapsum ~== "55E321849F3699655D7E062C90682F63") ) return MAP_HMAP12; if ( (mapsum ~== "E3B06F44DBF6F7E7754D7B1DAEF707E4") || (mapsum ~== "FC832437D7A2B7094A9B56C3909773D9") || (mapsum ~== "91AD797F95CC4C6D6AE33B21F664C60B") || (mapsum ~== "188B1B4244BD8DA501D8532696EC8654") || (mapsum ~== "5B29D0889DF09A8250D62FA09EB2B452") || (mapsum ~== "D3C5FA777BA52264546E6569F167AF0D") || (mapsum ~== "15FC0991D975325556EFF71F241A4458") || (mapsum ~== "2FAD54B58487884F06EAFA507B553921") ) return MAP_HMAP23_HMAP27_HMAP48_HMAP55; if ( (mapsum ~== "4444C95C2029DA6EECAC92DAA31CE665") || (mapsum ~== "33752742BCA8E539A6EE3E5D0FDA8744") || (mapsum ~== "3FFAF2F624C1B4BB6F581DCF7B99CBA7") ) return MAP_HMAP36; if ( (mapsum ~== "78979A583B1E30D94C9DAE2BCFA9A18D") || (mapsum ~== "FDC90F44C65A71E0901C1B9FFFCF3D02") || (mapsum ~== "088ECE0E0F3E68448FA1D901001A0084") ) return MAP_HMAP37; if ( (mapsum ~== "3BF62E4F9FB3CF9AF267421CE2D5F348") || (mapsum ~== "4799E1FDB5A3C0E3AD650B5AC215A737") || (mapsum ~== "5C63A02B0B04D9AE95CA51687DC3406F") ) return MAP_HMAP38; if ( (mapsum ~== "EFAFE59092DE5E613562ACF52B86C37F") || (mapsum ~== "1C5DE5A921DEE405E98E7E09D9829387") || (mapsum ~== "2A6C4235B942467D25FD50D5B313E67A") ) return MAP_HMAP40; if ( mapsum ~== "B0ADDB295A3ACCE43978AAC91FB8C58A" ) return MAP_HMAP60; if ( mapsum ~== "5C5E5C08AF3572F31CF27318679F2B4E" ) return MAP_EVMAP30; return MAP_NONE; } static void QueueCasing( SWWMCasing c ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd ) return; hnd.casings_cnt++; if ( !hnd.casings ) { // this is the initial one hnd.casings = c; hnd.casings_end = c; } else { hnd.casings_end.nextcasing = c; c.prevcasing = hnd.casings_end; hnd.casings_end = c; } while ( hnd.casings && (swwm_maxcasings >= 0) && (hnd.casings_cnt > swwm_maxcasings) ) DeQueueCasing(hnd.casings); } static void DeQueueCasing( SWWMCasing c ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd || !hnd.casings ) return; if ( (hnd.casings != c) && !c.prevcasing && !c.nextcasing ) return; hnd.casings_cnt--; if ( !c.prevcasing ) hnd.casings = c.nextcasing; else c.prevcasing.nextcasing = c.nextcasing; if ( c == hnd.casings_end ) hnd.casings_end = c.prevcasing; if ( c.nextcasing ) c.nextcasing.prevcasing = c.prevcasing; c.killme = true; c.prevcasing = null; c.nextcasing = null; } static void QueueChip( SWWMChip c ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd ) return; hnd.chips_cnt++; if ( !hnd.chips ) { // this is the initial one hnd.chips = c; hnd.chips_end = c; } else { hnd.chips_end.nextchip = c; c.prevchip = hnd.chips_end; hnd.chips_end = c; } while ( hnd.chips && (swwm_maxdebris >= 0) && (hnd.chips_cnt > swwm_maxdebris) ) DeQueueChip(hnd.chips); } static void DeQueueChip( SWWMChip c ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd || !hnd.chips ) return; if ( (hnd.chips != c) && !c.prevchip && !c.nextchip ) return; hnd.chips_cnt--; if ( !c.prevchip ) hnd.chips = c.nextchip; else c.prevchip.nextchip = c.nextchip; if ( c == hnd.chips_end ) hnd.chips_end = c.prevchip; if ( c.nextchip ) c.nextchip.prevchip = c.prevchip; c.killme = true; c.prevchip = null; c.nextchip = null; } static void QueueBlod( mkBloodDrop b ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); 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 && (swwm_maxblood >= 0) && (hnd.blods_cnt > swwm_maxblood) ) DeQueueBlod(hnd.blods); } static void DeQueueBlod( mkBloodDrop b ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); 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 = SWWMHandler(EventHandler.Find("SWWMHandler")); 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 && (swwm_maxgibs >= 0) && (hnd.meats_cnt > swwm_maxgibs) ) DeQueueMeat(hnd.meats); } static void DeQueueMeat( mkFlyingGib m ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); 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; } static void HealthFlash( int p ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd || (p == -1) ) return; hnd.hflash[p] = gametic+5; } static void ArmorFlash( int p ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd || (p == -1) ) return; hnd.aflash[p] = gametic+5; } static int AddOneliner( String type, int level, int delay = 5 ) { // only Demolitionist can play voice lines if ( !(players[consoleplayer].mo is 'Demolitionist') ) return 0; let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd ) return 0; String voicetype = CVar.FindCVar('swwm_voicetype').GetString(); // suppress non-rage comments when ragekit is active, only screaming allowed if ( players[consoleplayer].mo.FindInventory("RagekitPower") && (type != "ragekit") ) return 0; int whichline; String testme = String.Format("SWWM_SUBS_%s_N%s",voicetype.MakeUpper(),type.MakeUpper()); String locme = StringTable.Localize(testme,false); int countem; if ( testme == locme ) countem = 0; else countem = locme.ToInt(); if ( countem == 0 ) return 0; // voicepack doesn't have this // check last line so we don't repeat int last = 0, ent; for ( int i=0; i 0 ) { whichline = Random[DemoLines](1,countem-1); if ( whichline >= last ) whichline++; hnd.lastlines[ent].lineno = whichline; } else { whichline = Random[DemoLines](1,countem); let lst = new("LastLine"); lst.type = type; lst.lineno = whichline; hnd.lastlines.Push(lst); } hnd.oneliner = String.Format("$SWWM_SUBS_%s_%s%d",voicetype.MakeUpper(),type.MakeUpper(),whichline); hnd.onelinersnd = String.Format("voice/%s/%s%d",voicetype,type,whichline); hnd.onelinertic = gametic+delay; hnd.onelinerspan = int(S_GetLength(hnd.onelinersnd)*GameTicRate); hnd.onelinerlevel = level; return hnd.onelinertic+hnd.onelinerspan; } override void OnRegister() { // oneliner RNG must be relative to consoleplayer SetRandomSeed[DemoLines](Random[DemoLines]()+consoleplayer+MSTime()); // "uninitialize" some vars iwantdie = -1; bossmap = -1; indoomvacation = -1; // this one can be initialized here easily for ( int i=0; i l.backsector.floorplane.ZatPoint(l.v1.p)) && (l.frontsector.floorplane.ZatPoint(l.v2.p) > l.backsector.floorplane.ZatPoint(l.v2.p)) ) { highestfloor = l.frontsector.floorplane; lowestfloor = l.backsector.floorplane; } else { highestfloor = l.backsector.floorplane; lowestfloor = l.frontsector.floorplane; } if ( (l.frontsector.ceilingplane.ZatPoint(l.v1.p) < l.backsector.ceilingplane.ZatPoint(l.v1.p)) && (l.frontsector.ceilingplane.ZatPoint(l.v2.p) < l.backsector.ceilingplane.ZatPoint(l.v2.p)) ) { lowestceiling = l.frontsector.ceilingplane; highestceiling = l.backsector.ceilingplane; } else { lowestceiling = l.backsector.ceilingplane; highestceiling = l.frontsector.ceilingplane; } // try to guess what the part that triggers this is if ( l.Activation&SPAC_Cross ) { // pick the "intersection" al = (l.v1.p,highestfloor.ZatPoint(l.v1.p)); ah = (l.v1.p,lowestceiling.ZatPoint(l.v1.p)); bl = (l.v2.p,highestfloor.ZatPoint(l.v2.p)); bh = (l.v2.p,lowestceiling.ZatPoint(l.v2.p)); return (al+ah+bl+bh)*.25; } // check if lower part available al = (l.v1.p,lowestfloor.ZatPoint(l.v1.p)); ah = (l.v1.p,highestfloor.ZatPoint(l.v1.p)); bl = (l.v2.p,lowestfloor.ZatPoint(l.v2.p)); bh = (l.v2.p,highestfloor.ZatPoint(l.v2.p)); if ( ((al-ah).length() > 0) && ((bl-bh).length() > 0) ) return (al+ah+bl+bh)*.25; // check if upper part available al = (l.v1.p,lowestceiling.ZatPoint(l.v1.p)); ah = (l.v1.p,highestceiling.ZatPoint(l.v1.p)); bl = (l.v2.p,lowestceiling.ZatPoint(l.v2.p)); bh = (l.v2.p,highestceiling.ZatPoint(l.v2.p)); if ( ((al-ah).length() > 0) && ((bl-bh).length() > 0) ) return (al+ah+bl+bh)*.25; // check for 3d floors bool floorfound = false; Vector3 fal, fah, fbl, fbh; for ( int i=0; i ah.z) && (fbh.z > bh.z) && (fal.z > al.z) && (fbl.z > bl.z) ) continue; al = fal; ah = fah; bl = fbl; bh = fbh; floorfound = true; } if ( floorfound ) return (al+ah+bl+bh)*.25; for ( int i=0; i ah.z) && (fbh.z > bh.z) && (fal.z > al.z) && (fbl.z > bl.z) ) continue; al = fal; ah = fah; bl = fbl; bh = fbh; floorfound = true; } if ( floorfound ) return (al+ah+bl+bh)*.25; // check for midtex if ( !l.sidedef[0].GetTexture(1).IsNull() ) { double ofs = l.sidedef[0].GetTextureYOffset(1); Vector2 siz = TexMan.GetScaledSize(l.sidedef[0].GetTexture(1)); Vector2 tofs = TexMan.GetScaledOffset(l.sidedef[0].GetTexture(1)); ofs += tofs.y; ofs *= l.sidedef[0].GetTextureYScale(1); siz.y *= l.sidedef[0].GetTextureYScale(1); if ( l.flags&Line.ML_DONTPEGBOTTOM ) { al = (l.v1.p,highestfloor.ZAtPoint(l.v1.p)+ofs); bl = (l.v2.p,highestfloor.ZAtPoint(l.v2.p)+ofs); ah = al+(0,0,siz.y); bh = bl+(0,0,siz.y); } else { ah = (l.v1.p,lowestceiling.ZAtPoint(l.v1.p)+ofs); bh = (l.v2.p,lowestceiling.ZAtPoint(l.v2.p)+ofs); al = ah-(0,0,siz.y); bl = bh-(0,0,siz.y); } return (al+ah+bl+bh)*.25; } if ( !l.sidedef[1].GetTexture(1).IsNull() ) { double ofs = l.sidedef[1].GetTextureYOffset(1); Vector2 siz = TexMan.GetScaledSize(l.sidedef[1].GetTexture(1)); Vector2 tofs = TexMan.GetScaledOffset(l.sidedef[1].GetTexture(1)); ofs += tofs.y; ofs *= l.sidedef[1].GetTextureYScale(1); siz.y *= l.sidedef[1].GetTextureYScale(1); if ( l.flags&Line.ML_DONTPEGBOTTOM ) { al = (l.v1.p,highestfloor.ZAtPoint(l.v1.p)+ofs); bl = (l.v2.p,highestfloor.ZAtPoint(l.v2.p)+ofs); ah = al+(0,0,siz.y); bh = bl+(0,0,siz.y); } else { ah = (l.v1.p,lowestceiling.ZAtPoint(l.v1.p)+ofs); bh = (l.v2.p,lowestceiling.ZAtPoint(l.v2.p)+ofs); al = ah-(0,0,siz.y); bl = bh-(0,0,siz.y); } return (al+ah+bl+bh)*.25; } // just use the intersection al = (l.v1.p,highestfloor.ZatPoint(l.v1.p)); ah = (l.v1.p,lowestceiling.ZatPoint(l.v1.p)); bl = (l.v2.p,highestfloor.ZatPoint(l.v2.p)); bh = (l.v2.p,lowestceiling.ZatPoint(l.v2.p)); return (al+ah+bl+bh)*.25; } static clearscope void ClearAllShaders( PlayerInfo p ) { Shader.SetEnabled(p,"WaterWarp",false); Shader.SetEnabled(p,"LavaWarp",false); Shader.SetEnabled(p,"SlimeWarp",false); 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); } // level end stats override void WorldUnloaded( WorldEvent e ) { let ti = ThinkerIterator.Create("SWWMStats",Thinker.STAT_STATIC); SWWMStats s; while ( s = SWWMStats(ti.Next()) ) { if ( !(gameinfo.gametype&GAME_STRIFE) ) { int clust = 0; bool secret = false; if ( SWWMUtility.IsEviternity() ) { // we have to do some heavy lifting here because episodes don't match clusters if ( level.levelnum <= 5 ) clust = 1; else if ( level.levelnum <= 10 ) clust = 2; else if ( level.levelnum <= 15 ) clust = 3; else if ( level.levelnum <= 20 ) clust = 4; else if ( level.levelnum <= 25 ) clust = 5; else if ( level.levelnum <= 30 ) clust = 6; else if ( level.levelnum <= 32 ) { secret = true; if ( level.levelnum <= 31 ) clust = 7; else clust = 8; } } else { if ( (gameinfo.gametype&GAME_DOOM) && ((level.cluster == 9) || (level.cluster == 10)) ) secret = true; clust = level.cluster; } int csiz = s.clustervisit.Size(); if ( csiz == 0 ) { s.clustervisit.Push(clust); s.secretdone.Push(secret); } else if ( s.clustervisit[csiz-1] != clust ) { s.clustervisit.Push(clust); s.secretdone.Push(secret|s.secretdone[csiz-1]); } } s.AddLevelStats(); s.lastcluster = level.cluster; } ClearAllShaders(players[consoleplayer]); // reset score on dead players (death exitâ„¢) for ( int i=0; i 0) ) continue; let c = SWWMCredits.Find(players[i]); if ( c ) c.credits = c.hcredits = 0; } // end of episode resets if ( level.nextsecretmap.Left(6) == "enDSeQ" ) { for ( int i=0; i lines; lines.Clear(); data.Split(lines,"\n"); bool valid = false; for ( int j=0; j spl; spl.Clear(); lines[j].Split(spl," ",TOK_SKIPEMPTY); // check game string (if any) if ( spl.Size() > 2 ) { if ( (spl[2] ~== "DOOM") && !(gameinfo.gametype&GAME_Doom) ) continue; else if ( (spl[2] ~== "HERETIC") && !(gameinfo.gametype&GAME_Heretic) ) continue; else if ( (spl[2] ~== "HEXEN") && !(gameinfo.gametype&GAME_Hexen) ) continue; else if ( (spl[2] ~== "STRIFE") && !(gameinfo.gametype&GAME_Strife) ) continue; else if ( (spl[2] ~== "CHEX") && !(gameinfo.gametype&GAME_Chex) ) continue; } // valid lock, prepare it let li = new("LIEntry"); li.locknumber = spl[1].ToInt(); li.hascolor = false; // see if there's a Mapcolor defined int k = j+1; for ( int k=j+2; k skipme; skipme.Clear(); // find exit lines, and use lines that aren't exits for ( int i=0; i swwm_maxcasings) ) DeQueueCasing(casings); while ( chips && (chips_cnt > swwm_maxdebris) ) DeQueueChip(chips); while ( blods && (blods_cnt > swwm_maxblood) ) DeQueueBlod(blods); while ( meats && (meats_cnt > swwm_maxgibs) ) DeQueueMeat(meats); } override void PlayerDied( PlayerEvent e ) { let s = SWWMStats.Find(players[e.playernumber]); if ( s ) s.deaths++; } override void PlayerEntered( PlayerEvent e ) { PlayerInfo p = players[e.playernumber]; // override KEYCONF-forced player classes when run with other gameplay mods (wish this was easier) if ( !(p.mo is 'Demolitionist') ) { // make sure it's defined here, so special purpose classes (player chunks, scripted overrides) are respected for ( int i=0; i 0) && ((s.lastcluster != level.cluster) || !(level.clusterflags&LevelLocals.CLUSTER_HUB))) ) SWWMUtility.WipeInventory(p.mo,swwm_resetscore); } override void PlayerRespawned( PlayerEvent e ) { // reset some vars multilevel[e.playernumber] = 0; spreecount[e.playernumber] = 0; tookdamage[e.playernumber] = false; lastkill[e.playernumber] = int.min; // reset combat tracker if ( !swwm_notrack ) SWWMCombatTracker.Spawn(players[e.playernumber].mo); } override void WorldThingRevived( WorldEvent e ) { // reattach combat tracker if ( !swwm_notrack && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER) && !(e.Thing is 'LampMoth') && !(e.Thing is 'CompanionLamp') ) SWWMCombatTracker.Spawn(e.Thing); // reattach headpats if ( SWWMUtility.IdentifyingDog(e.Thing) || SWWMUtility.IdentifyingCaco(e.Thing) || SWWMUtility.IdentifyingDrug(e.Thing) || SWWMUtility.IdentifyingDoubleBoi(e.Thing) ) { // you can pet the dog, and you can also pet the caco (and friends) let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; } if ( !(e.Thing is 'PlayerPawn') ) return; // reset some vars if ( e.Thing.playernumber() != -1 ) { multilevel[e.Thing.playernumber()] = 0; spreecount[e.Thing.playernumber()] = 0; tookdamage[e.Thing.playernumber()] = false; lastkill[e.Thing.playernumber()] = int.min; } // reset uptime since player had just died SWWMStats s = SWWMStats.Find(e.Thing.player); if ( s ) s.lastspawn = level.totaltime; } private void LangRefresh() { if ( (language != curlang) || (swwm_funtags != curfuntags) ) { // manually refresh some tags if language has changed for ( SWWMCombatTracker t=trackers; t; t=t.next ) t.UpdateTag(); for ( SWWMInterest p=intpoints; p; p=p.next ) { if ( (p.type != INT_Key) || !p.trackedkey ) continue; p.keytag = p.trackedkey.GetTag(); } for ( int i=0; i= 0) && (casings_cnt > swwm_maxcasings) ) DeQueueCasing(casings); } if ( swwm_maxdebris != oldmaxdebris ) { while ( chips && (swwm_maxdebris >= 0) && (chips_cnt > swwm_maxdebris) ) DeQueueChip(chips); } if ( swwm_maxblood != oldmaxblood ) { while ( blods && (swwm_maxblood >= 0) && (blods_cnt > swwm_maxblood) ) DeQueueBlod(blods); } if ( swwm_maxgibs != oldmaxgibs ) { while ( meats && (swwm_maxgibs >= 0) && (meats_cnt > swwm_maxgibs) ) DeQueueMeat(meats); } oldmaxcasings = swwm_maxcasings; oldmaxdebris = swwm_maxdebris; oldmaxblood = swwm_maxblood; oldmaxgibs = swwm_maxgibs; if ( swwm_blood ) return; while ( blods ) DeQueueBlod(blods); while ( meats ) DeQueueMeat(meats); } // countable item scoring private void ItemCountTrack() { for ( int i=0; i lastitemcount[i] ) { int score = 10*(players[i].itemcount-lastitemcount[i]); if ( (level.total_items == level.found_items) && !allitems ) { allitems = true; Console.Printf(StringTable.Localize("$SWWM_LASTITEM"),players[i].GetUserName(),500); score += 490; } SWWMCredits.Give(players[i],score); SWWMScoreObj.Spawn(score,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2)); lastitemcount[i] = players[i].itemcount; let s = SWWMStats.Find(players[i]); s.items++; } } } // combat tracking private void CombatTrack() { // prune old entries for ( int i=0; i highesttic ) highesttic = combattics[i]; if ( combatactors[i] && (combatactors[i].Health > 0) && !combatactors[i].bKILLED && !combatactors[i].bCORPSE && (combatactors[i].target == players[consoleplayer].mo) && (combattics[i]+2000 > gametic) ) continue; combatactors.Delete(i); combattics.Delete(i); i--; } bool enteredcombat = false; // add new entries let ti = ThinkerIterator.Create("Actor"); Actor a; while ( a = Actor(ti.Next()) ) { if ( !a.player && !a.bISMONSTER ) continue; // ignore the dead if ( (a.Health <= 0) || a.bKILLED || a.bCORPSE ) continue; // ignore friends if ( a.IsFriend(players[consoleplayer].mo) ) continue; // [Strife] ignore if not in combat if ( (gameinfo.gametype&GAME_Strife) && !a.bINCOMBAT && !a.bJUSTATTACKED ) continue; // [Strife] ignore certain classes if ( (a is 'RatBuddy') || (a is 'Peasant') || (a is 'Beggar') ) continue; // [Strife] ignore Oracle's spectre while it's inactive if ( (a is 'AlienSpectre3') && a.InStateSequence(a.CurState,a.FindState("Spawn")) ) continue; // ignore if not targetted or player can't see it if ( (a.target != players[consoleplayer].mo) || !SWWMUtility.InPlayerFOV(players[consoleplayer],a) ) continue; // [HDoom] ignore cute girls if ( SWWMHDoomHandler.IsCuteGirl(a.target) ) continue; // is it already in? bool addme = true; for ( int i=0; i highesttic+700)) ) lastcombat = AddOneliner("fightstart",1,10); } private void OneHundredPercentCheck() { if ( !mapclear && (restartmus > 0) ) { restartmus--; if ( restartmus == 0 ) S_ChangeMusic(lastmus,lastorder,lastloop,true); return; } // ignore levels that have NOTHING if ( (level.total_secrets <= 0) && (level.total_items <= 0) && (level.total_monsters <= 0) ) return; if ( mapclear ) { if ( (swwm_silencemap == 1) && (musplaying.name != "") ) { lastmus = musplaying.name; lastorder = musplaying.baseorder; lastloop = musplaying.loop; S_ChangeMusic("",force:true); } else if ( (swwm_silencemap > 1) && (musplaying.name != "music/olg.ogg") ) { lastmus = musplaying.name; lastorder = musplaying.baseorder; lastloop = musplaying.loop; S_ChangeMusic("music/olg.ogg",force:true); } if ( (level.found_secrets < level.total_secrets) || (level.found_items < level.total_items) || (level.killed_monsters < level.total_monsters) ) { if ( swwm_silencemap > 0 ) { restartmus = 25; S_ChangeMusic("",force:true); } S_StartSound("recordscratch",CHAN_VOICE,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE); mapclear = false; if ( mapclearagain > 1 ) Console.Printf(StringTable.Localize("$SWWM_NOTCLEARAGAIN")); else Console.Printf(StringTable.Localize("$SWWM_NOTCLEAR")); } return; } if ( (level.found_secrets < level.total_secrets) || (level.found_items < level.total_items) || (level.killed_monsters < level.total_monsters) ) return; restartmus = 0; mapclear = true; if ( mapclearagain ) Console.Printf(StringTable.Localize("$SWWM_ALLCLEARAGAIN"),500); else Console.Printf(StringTable.Localize("$SWWM_ALLCLEAR"),5000); S_StartSound("misc/wow",CHAN_VOICE,CHANF_UI|CHANF_NOPAUSE|CHANF_OVERLAP,1,ATTN_NONE); lastmus = musplaying.name; lastorder = musplaying.baseorder; lastloop = musplaying.loop; if ( swwm_silencemap == 1 ) S_ChangeMusic("",force:true); else if ( swwm_silencemap > 1 ) S_ChangeMusic("music/olg.ogg",force:true); for ( int i=0; i viewdist ) continue; if ( a == players[consoleplayer].Camera ) continue; if ( !a.player && !a.bSOLID && !a.bSHOOTABLE && !a.bISMONSTER && !a.bFRIENDLY && !(a is 'Inventory') && !(a is 'Chancebox') ) continue; if ( !thesight && !a.IsFriend(players[consoleplayer].mo) && !players[consoleplayer].Camera.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue; if ( a.bKILLED || (a.Health <= 0) ) continue; if ( (a is 'Inventory') && (!a.bSPECIAL || Inventory(a).Owner) ) continue; if ( (a is 'Chancebox') && (a.CurState != a.SpawnState) ) continue; SWWMSimpleTracker.Track(a); } SWWMSimpleTracker trk = strackers; while ( trk ) { SWWMSimpleTracker next = trk.next; // minimize lifespan of destroyed targets if ( !trk.target ) trk.lastupdate = min(trk.lastupdate,level.maptime); else if ( !trk.expired ) { // "last breath" update if ( (trk.target.bKILLED || (trk.target.Health <= 0)) || ((trk.target is 'Inventory') && (!trk.target.bSPECIAL || Inventory(trk.target).Owner)) || ((trk.target is 'Chancebox') && (trk.target.CurState != trk.target.SpawnState)) ) trk.Update(); } // prune expired trackers if ( trk.lastupdate+140 < level.maptime ) { if ( !trk.prev ) strackers = trk.next; else trk.prev.next = trk.next; if ( trk.next ) trk.next.prev = trk.prev; trk.Destroy(); strackers_cnt--; } trk = next; } } override void WorldTick() { LangRefresh(); QueueMaintenance(); if ( !(gameinfo.gametype&GAME_STRIFE) && !mnotify && (level.maptime >= 5) ) { mnotify = true; let ti = ThinkerIterator.Create("SWWMStats",Thinker.STAT_STATIC); SWWMStats s; while ( s = SWWMStats(ti.Next()) ) { if ( !SWWMUtility.IsKnownMap() ) break; if ( s.myplayer != players[consoleplayer] ) continue; int clust = level.cluster; if ( SWWMUtility.IsEviternity() ) { // we have to do some heavy lifting here because episodes don't match clusters if ( level.levelnum <= 5 ) clust = 1; else if ( level.levelnum <= 10 ) clust = 2; else if ( level.levelnum <= 15 ) clust = 3; else if ( level.levelnum <= 20 ) clust = 4; else if ( level.levelnum <= 25 ) clust = 5; else if ( level.levelnum <= 30 ) clust = 6; else if ( level.levelnum <= 31 ) clust = 7; else if ( level.levelnum <= 32 ) clust = 8; } int csiz = s.clustervisit.Size(); if ( (csiz > 0) && (s.clustervisit[csiz-1] != clust) ) Console.Printf(StringTable.Localize("$SWWM_NEWMISSION")); } } if ( onelinertic && (onelinertic < gametic) ) { if ( players[consoleplayer].health > 0 ) { if ( onelinerlevel > swwm_mutevoice ) players[consoleplayer].mo.A_StartSound(onelinersnd,CHAN_DEMOVOICE,CHANF_DEFAULT,1.,ATTN_NONE); SendNetworkEvent("swwmremoteliner."..onelinersnd,consoleplayer,onelinerlevel); } onelinertic = 0; onelinerspan = 0; } for ( int i=0; i= gametic ) continue; flashes.Delete(i); i--; } ItemCountTrack(); CombatTrack(); OneHundredPercentCheck(); SimpleTracking(); if ( initialized ) return; // wait until bosses are active for ( int i=0; i 0); } override void WorldThingDied( WorldEvent e ) { if ( e.Thing.default.bISMONSTER && ((e.Thing.default.bBOSS) || (e.Thing.GetSpawnHealth() >= 1000)) && (alreadygold.Find(e.Thing) == alreadygold.Size()) ) { // make sure we can't farm drops from revivable enemies // (or cause some things to spam-spawn gold shells) // (*cough* Touhou Doom *cough*) alreadygold.Push(e.Thing); // weight drop chance based on total count of this monster type // guarantees that maps that get a bit slaughtery won't become easy farms for drops int dropweight = 0; let ti = ThinkerIterator.Create(e.Thing.GetClass()); while ( ti.Next() ) dropweight++; int minchance = max(1,6-(e.Thing.GetSpawnHealth()/1000)); dropweight = max(minchance,dropweight/4); // make sure the gold shell is "worth spawning", too if ( !Random[GoldDrop](0,dropweight) && ShouldSpawnGold() ) { let g = Actor.Spawn("GoldShell",e.Thing.Vec3Offset(0,0,e.Thing.Height/2)); double ang = FRandom[SpareShells](0,360); g.vel.xy = (cos(ang),sin(ang))*FRandom[SpareShells](.4,.8); g.vel.z = FRandom[SpareShells](2.,4.); } } // Korax instakill if ( (e.Thing is 'Korax') && !e.Thing.special2 && HexenMap40() ) { e.Thing.special2 = 1; // terminate the monster closet scripts, open all the // doors ourselves level.ExecuteSpecial(ACS_Terminate,e.Thing,null,false,220); level.ExecuteSpecial(ACS_Terminate,e.Thing,null,false,220); level.ExecuteSpecial(ACS_Terminate,e.Thing,null,false,221); level.ExecuteSpecial(ACS_Terminate,e.Thing,null,false,255); level.ExecuteSpecial(Door_Open,e.Thing,null,false,10,16); level.ExecuteSpecial(Door_Open,e.Thing,null,false,11,16); level.ExecuteSpecial(Door_Open,e.Thing,null,false,12,16); level.ExecuteSpecial(Door_Open,e.Thing,null,false,13,16); level.ExecuteSpecial(Door_Open,e.Thing,null,false,14,16); level.ExecuteSpecial(Door_Open,e.Thing,null,false,10,16); // keep the portal closed, you can't leave unless you // kill everyone else let t = new("UglyBoyGetsFuckedUp"); t.ChangeStatNum(Thinker.STAT_USER); } if ( swwm_partytime ) { let pt = Actor.Spawn("PartyTime",e.Thing.pos); pt.target = e.Thing; } // force insert gib animations on some vanilla Doom monsters int gibhealth = e.Thing.GetGibHealth(); bool gotgibbed = (!e.Thing.bDONTGIB && ((e.Inflictor && e.Inflictor.bEXTREMEDEATH) || (e.DamageSource && e.DamageSource.bEXTREMEDEATH) || (e.DamageType == 'Extreme') || (e.Thing.Health < gibhealth)) && (!e.Inflictor || !e.Inflictor.bNOEXTREMEDEATH) && (!e.DamageSource || !e.DamageSource.bNOEXTREMEDEATH)); if ( !gotgibbed ) return; if ( (e.Thing.GetClass() == "Demon") || (e.Thing.GetClass() == "Spectre") ) ExtraGibDeaths.GibThis(e.Thing,"DemonXDeath"); else if ( e.Thing.GetClass() == "HellKnight" ) ExtraGibDeaths.GibThis(e.Thing,"KnightXDeath"); else if ( e.Thing.GetClass() == "BaronOfHell" ) ExtraGibDeaths.GibThis(e.Thing,"BaronXDeath"); else if ( e.Thing.GetClass() == "Cacodemon" ) ExtraGibDeaths.GibThis(e.Thing,"CacoXDeath"); else if ( e.Thing.GetClass() == "Revenant" ) ExtraGibDeaths.GibThis(e.Thing,"BonerXDeath"); else if ( e.Thing.GetClass() == "Archvile" ) ExtraGibDeaths.GibThis(e.Thing,"VileXDeath"); } // gibbing private void DoGibThing( WorldEvent e ) { // no gib if it was erased or used the kill monsters cheat if ( (e.DamageType == 'Ynykron') || (e.DamageType == 'Massacre') ) return; int gibhealth = e.Thing.GetGibHealth(); bool gotgibbed = (!e.Thing.bDONTGIB && ((e.Inflictor && e.Inflictor.bEXTREMEDEATH) || (e.DamageSource && e.DamageSource.bEXTREMEDEATH) || (e.DamageType == 'Extreme') || (e.Thing.Health < gibhealth)) && (!e.Inflictor || !e.Inflictor.bNOEXTREMEDEATH) && (!e.DamageSource || !e.DamageSource.bNOEXTREMEDEATH)); bool forcegibbed = false; // force gib availability for some vanilla Doom monsters if ( gotgibbed && ((e.Thing.GetClass() == "Demon") || (e.Thing.GetClass() == "Spectre") || (e.Thing.GetClass() == "HellKnight") || (e.Thing.GetClass() == "BaronOfHell") || (e.Thing.GetClass() == "Cacodemon") || (e.Thing.GetClass() == "Revenant") || (e.Thing.GetClass() == "Archvile")) ) forcegibbed = true; if ( !e.Thing.FindState("XDeath",true) && !e.Thing.FindState("Death.Extreme",true) && !forcegibbed ) gotgibbed = false; // only do special handling if they use our blood if ( (e.Thing.GetBloodType(0) != "mkBlood") || e.Thing.bNOBLOOD ) return; CorpseFallTracker.TrackBody(e.Thing); bool b; Actor a; // special handling of some monsters if ( e.Thing.GetClass() == "Cyberdemon" ) { [b,a] = e.Thing.A_SpawnItemEx("mkGibber",flags:SXF_USEBLOODCOLOR); if ( !b ) return; mkGibber(a).gibbed = e.Thing; mkGibber(a).delay = 40; a.A_SetSize(e.Thing.default.radius,e.Thing.default.height); return; } else if ( e.Thing.GetClass() == "SpiderMastermind" ) { [b,a] = e.Thing.A_SpawnItemEx("mkGibber",flags:SXF_USEBLOODCOLOR); if ( !b ) return; mkGibber(a).gibbed = e.Thing; mkGibber(a).delay = 60; a.A_SetSize(e.Thing.default.radius,e.Thing.default.height); } else if ( gotgibbed ) { [b,a] = e.Thing.A_SpawnItemEx("mkGibber",flags:SXF_USEBLOODCOLOR); if ( !b ) return; mkGibber(a).gibbed = e.Thing; a.A_SetSize(e.Thing.default.radius,e.Thing.default.height); } } // damage numbers, combat tracking, etc. private void DoDamageHandling( WorldEvent e ) { bool spawnme = true; if ( swwm_accdamage ) { // find existing damage number for ( SWWMScoreObj d=damnums; d; d=d.next ) { if ( (d.starttic < level.maptime) || (d.acc != e.Thing) ) continue; if ( d.score-e.Damage > d.score ) d.score = int.min; else d.score -= e.Damage; spawnme = false; break; } } if ( spawnme ) SWWMScoreObj.Spawn(-e.Damage,e.Thing.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+e.Thing.Height/2),ST_Damage,e.Thing); // update combat tracker for it if ( !(e.Thing is 'BossBrain') ) { for ( SWWMCombatTracker t=trackers; t; t=t.next ) { if ( t.mytarget != e.Thing ) continue; t.updated = level.maptime+35; break; } } // fall dmg SWWMWhoPushedMe.SetInstigator(e.Thing,e.DamageSource); // stats if ( e.Thing.player ) { tookdamage[e.Thing.PlayerNumber()] = true; let s = SWWMStats.Find(e.Thing.player); if ( s ) // deathmatch telefrag-on-spawn may cause this to be null { s.AddDamageTaken(e.Damage); if ( e.Damage > s.toptaken ) s.toptaken = e.Damage; } } if ( e.DamageSource && e.DamageSource.player ) { let s = SWWMStats.Find(e.DamageSource.player); if ( s ) // deathmatch telefrag-on-spawn may cause this to be null { s.AddDamageDealt(e.Damage); if ( e.Damage > s.topdealt ) s.topdealt = e.Damage; } } } // combat hit chatter private void DoCombatHit( WorldEvent e ) { if ( (e.DamageSource.bISMONSTER || e.DamageSource.player || (e.DamageSource is 'ScriptedMarine')) && (e.Thing == players[consoleplayer].mo) && (e.Thing.Health > 0) ) { if ( !lastcombat || (gametic > lastcombat+40) ) { if ( (e.Thing.IsFriend(e.DamageSource) || SWWMUtility.IsCivilian(e.DamageSource)) ) lastcombat = AddOneliner("friendhit",1,10); else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,e.DamageSource.bBOSS?2:4) && !SWWMHDoomHandler.IsCuteGirl(e.DamageSource) ) // [HDoom] don't shout at the girls lastcombat = AddOneliner("gethit",1,15); } highesttic = gametic; } // friendly fire lines only fire up if we didn't kill them right away (because then the teamkill line should take priority) if ( (e.DamageSource == players[consoleplayer].mo) && (e.Thing.bISMONSTER || e.Thing.player || (e.Thing is 'ScriptedMarine')) && (e.Thing.Health > 0) ) { // make sure it's not a moth, because otherwise they won't shut up about accidentally hurting them (it happens a lot) if ( (e.Thing.IsFriend(e.DamageSource) || SWWMUtility.IsCivilian(e.Thing)) && !(e.Thing is 'LampMoth') ) { if ( !lastcombat || (gametic > lastcombat+40) ) lastcombat = AddOneliner("hitfriend",1,10); highesttic = gametic; } } } // kill scoring private void DoKillScoring( WorldEvent e ) { // fall damage tracking hack let src = e.DamageSource; if ( (e.DamageType == 'Falling') && !e.DamageSource ) src = SWWMWhoPushedMe.RecallInstigator(e.Thing); if ( (!src || !src.player || (src == e.Thing)) ) return; let s = SWWMStats.Find(src.player); if ( s ) { s.kills++; s.AddWeaponKill(e.Inflictor,e.Thing,e.DamageType); } if ( src == players[consoleplayer].mo ) { highesttic = gametic; if ( !lastcombat || (gametic > lastcombat+40) ) { if ( e.Thing.IsFriend(src) || SWWMUtility.IsCivilian(e.Thing) ) lastcombat = AddOneliner("friendkill",1,5); else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,e.Thing.bBOSS?2:5) && !SWWMHDoomHandler.IsCuteGirl(e.Thing) ) // [HDoom] don't shout at the girls lastcombat = AddOneliner("scorekill",1,15); } } // no credits unless it's a counted kill or marine (that isn't friendly) if ( e.Thing.IsFriend(src) || (!e.Thing.default.bCountKill && !(e.Thing is 'ScriptedMarine')) ) return; int pnum = src.PlayerNumber(); if ( level.maptime < (lastkill[pnum]+5*GameTicRate) ) multilevel[pnum]++; else multilevel[pnum] = 0; if ( s && (multilevel[pnum]+1 > s.mkill) ) s.mkill = multilevel[pnum]+1; lastkill[pnum] = level.maptime; // scoring int score = min(1000,int(ceil(e.Thing.GetSpawnHealth()*.05)*10)); SWWMScoreObj scr = null; if ( src.player == players[consoleplayer] ) scr = SWWMScoreObj.Spawn(score,e.Thing.Vec3Offset(0,0,e.Thing.Height/2)); int ofs = 0; if ( e.DamageType == 'Push' ) { score += 500; if ( scr ) { scr.xscore[ofs] = 0; scr.xstr[ofs] = StringTable.Localize("$SWWM_SHAMEFUL"); scr.xcnt = ++ofs; } } else if ( e.DamageType == 'Buttslam' ) { score += 300; if ( scr ) { scr.xscore[ofs] = 0; scr.xstr[ofs] = StringTable.Localize("$SWWM_BUTTSLAM"); scr.xcnt = ++ofs; } } else if ( e.DamageType == 'Love' ) { score += 600; if ( scr ) { scr.xscore[ofs] = 0; scr.xtcolor[ofs] = Font.FindFontColor('BlushPink'); scr.xstr[ofs] = StringTable.Localize((e.Thing is 'WolfensteinSS')?"$SWWM_LOVED_ALT":"$SWWM_LOVED"); scr.xcnt = ++ofs; } } else if ( e.Inflictor is 'FroggyChair' ) { score += 1440; if ( scr ) { scr.xscore[ofs] = 0; scr.xtcolor[ofs] = Font.CR_GREEN; scr.xstr[ofs] = StringTable.Localize("$SWWM_FROGGED"); scr.xcnt = ++ofs; } } Inventory pb; if ( e.Inflictor && (pb = e.Inflictor.FindInventory('ParriedBuff')) ) { score += 200; if ( pb.special1&1 ) score += 200; if ( scr ) { scr.xscore[ofs] = 0; if ( pb.special1&1 ) scr.xstr[ofs] = StringTable.Localize("$SWWM_PPARRY"); else scr.xstr[ofs] = StringTable.Localize("$SWWM_PARRY"); 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; if ( scr ) { scr.xscore[ofs] = 0; scr.xstr[ofs] = StringTable.Localize("$SWWM_OVERKILL"); scr.xcnt = ++ofs; } } score = int(score*(1.+.5*min(multilevel[pnum],16))); if ( (multilevel[pnum] > 0) && scr ) { if ( scr ) { scr.xscore[ofs] = (multilevel[pnum]>=16)?int.max:(multilevel[pnum]+1); scr.xstr[ofs] = StringTable.Localize("$SWWM_MULTIKILL"); scr.xcnt = ++ofs; } } spreecount[pnum]++; if ( s && (spreecount[pnum] > s.skill) && !tookdamage[pnum] ) s.skill = spreecount[pnum]; if ( !tookdamage[pnum] ) { int spreebonus = 10*(spreecount[pnum]); // taper off after 10x (some people go really far with these, holy fuck) if ( spreecount[pnum] > 10 ) spreebonus = int(spreebonus*((spreecount[pnum]/10.)**.25)); score += 100+spreebonus; if ( (spreecount[pnum] > 0) && scr ) { scr.xscore[ofs] = spreecount[pnum]; scr.xstr[ofs] = StringTable.Localize("$SWWM_SPREEKILL"); scr.xcnt = ++ofs; } } if ( e.Thing.bBOSS ) { score += 2000; if ( scr ) { scr.xscore[ofs] = 0; scr.xstr[ofs] = StringTable.Localize("$SWWM_BOSSKILL"); scr.xcnt = ++ofs; } } SWWMCredits.Give(src.player,score); if ( scr ) scr.score = score; // update final score if ( (level.killed_monsters+1 == level.total_monsters) && !allkills ) { allkills = true; SWWMCredits.Give(src.player,1000); Console.Printf(StringTable.Localize("$SWWM_LASTMONSTER"),src.player.GetUserName(),1000); SWWMScoreObj.Spawn(1000,src.Vec3Offset(0,0,src.Height/2)); } } override void WorldThingDamaged( WorldEvent e ) { if ( e.Damage > 0 ) DoDamageHandling(e); if ( e.DamageSource && (e.DamageSource != e.Thing) ) DoCombatHit(e); if ( (e.Thing.Health > 0) || e.Thing.bKilled || e.Thing.bCorpse ) return; DoGibThing(e); // romero hax if ( (e.Thing is 'BossBrain') && (e.DamageType == 'Telefrag') ) e.DamageSource.DamageMobj(null,null,Actor.TELEFRAG_DAMAGE,'EndLevel'); // voodoo doll telefragging barrel hax (eviternity death exits) if ( (e.Thing is 'ExplosiveBarrel') && (e.DamageType == 'Telefrag') && e.DamageSource.player && (e.DamageSource.player.mo != e.DamageSource) ) e.DamageSource.DamageMobj(null,null,Actor.TELEFRAG_DAMAGE,'EndLevel'); if ( !e.Thing.player && !e.Thing.bIsMonster && !e.Thing.bCountKill && !(e.Thing is 'ScriptedMarine') ) return; DoKillScoring(e); } private void DoKeyTagFix( Actor a ) { if ( a is 'SWWMKey' ) return; // mod's custom keys are fine if ( a is 'RedCard' ) a.SetTag("$T_REDCARD"); else if ( a is 'BlueCard' ) a.SetTag("$T_BLUECARD"); else if ( a is 'YellowCard' ) a.SetTag("$T_YELLOWCARD"); else if ( a is 'RedSkull' ) a.SetTag("$T_REDSKULL"); else if ( a is 'BlueSkull' ) a.SetTag("$T_BLUESKULL"); else if ( a is 'YellowSkull' ) a.SetTag("$T_YELLOWSKULL"); else if ( a is 'KeyYellow' ) a.SetTag("$T_YELLOWKEY"); else if ( a is 'KeyGreen' ) a.SetTag("$T_GREENKEY"); else if ( a is 'KeyBlue' ) a.SetTag("$T_BLUEKEY"); else if ( a.GetClassName() == 'KeyRed' ) a.SetTag("$T_REDKEY"); else if ( a is 'KeySteel' ) a.SetTag("$T_KEYSTEEL"); else if ( a is 'KeyCave' ) a.SetTag("$T_KEYCAVE"); else if ( a is 'KeyAxe' ) a.SetTag("$T_KEYAXE"); else if ( a is 'KeyFire' ) a.SetTag("$T_KEYFIRE"); else if ( a is 'KeyEmerald' ) a.SetTag("$T_KEYEMERALD"); else if ( a is 'KeyDungeon' ) a.SetTag("$T_KEYDUNGEON"); else if ( a is 'KeySilver' ) a.SetTag("$T_KEYSILVER"); else if ( a is 'KeyRusted' ) a.SetTag("$T_KEYRUSTED"); else if ( a is 'KeyHorn' ) a.SetTag("$T_KEYHORN"); else if ( a is 'KeySwamp' ) a.SetTag("$T_KEYSWAMP"); else if ( a is 'KeyCastle' ) a.SetTag("$T_KEYCASTLE"); } // tempfix keys have no tags static void KeyTagFix( Actor a ) { let hnd = SWWMHandler(Find("SWWMHandler")); if ( hnd ) hnd.DoKeyTagFix(a); } // copies the floatbob of overlapping identical items, so it doesn't look weird private void CopyFloatBob( Actor a ) { let bt = BlockThingsIterator.Create(a,16); while ( bt.Next() ) { let t = bt.Thing; if ( !t || (t == a) || !(t is 'Inventory') || !(t.spawnpoint ~== a.spawnpoint) ) continue; a.floatbobphase = t.floatbobphase; a.angle = t.angle; // also copy angle break; } } override void WorldThingDestroyed( WorldEvent e ) { if ( !e.Thing.default.bSHOOTABLE || !e.Thing.default.bMISSILE ) return; // remove from suckables int pos = suckableactors.Find(e.Thing); if ( pos >= suckableactors.Size() ) return; suckableactors.Delete(pos); } override void WorldThingSpawned( WorldEvent e ) { // I WANT DIE if ( iwantdie == -1 ) iwantdie = (G_SkillName() == StringTable.Localize("$SWWM_SKLUNATIC")); if ( iwantdie ) { if ( e.Thing.bMISSILE && !e.Thing.FindInventory("DontDuplicate") && !e.Thing.IsZeroDamage() && (e.Thing.target && e.Thing.target.bISMONSTER && !e.Thing.target.player) ) { e.Thing.speed *= 2; e.Thing.vel *= 2; Vector3 x, y, z; double ang = e.Thing.target.target?e.Thing.AngleTo(e.Thing.target.target):e.Thing.angle; double pt = e.Thing.target.target?SWWMUtility.PitchTo(e.Thing,e.Thing.target.target,.5):e.Thing.pitch; [x, y, z] = swwm_CoordUtil.GetAxes(pt,ang,e.Thing.roll); int numpt = Random[ExtraMissiles](1,2); for ( int i=0; i x.ceilingz ) x.SetZ(x.ceilingz-x.height); if ( x.pos.z < x.floorz ) x.SetZ(x.floorz); if ( !x.TestMobjLocation() || !x.TestMobjZ() || !level.IsPointInLevel(x.pos) ) { x.ClearCounters(); x.Destroy(); } else { x.angle = e.Thing.angle; x.GiveInventory("DontDuplicate",1); break; } } } } } } if ( (e.Thing is 'TeleportDest') || (e.Thing is 'BossTarget') ) { let d = Actor.Spawn("SWWMTeleportDest",e.Thing.pos); d.bNOGRAVITY = e.Thing.bNOGRAVITY; } if ( e.Thing is 'Inventory' ) CopyFloatBob(e.Thing); if ( swwm_doomfall && e.Thing.bISMONSTER ) e.Thing.bFALLDAMAGE = true; if ( e.Thing is 'Key' ) { DoKeyTagFix(e.Thing); SWWMInterest.Spawn(thekey:Key(e.Thing)); } if ( indoomvacation == -1 ) indoomvacation = SWWMUtility.InDoomVacation(); if ( e.Thing.GetClass() == 'Pig' ) e.Thing.SetTag("$FN_PIG"); // missing in gzdoom // eviternity stuff else if ( (e.Thing.GetClassName() == "Archangelus") || (e.Thing.GetClassName() == "ArchangelusA") || (e.Thing.GetClassName() == "ArchangelusB") ) e.Thing.SetTag("$FN_ANGEL"); else if ( e.Thing.GetClassName() == "AstralCaco" ) e.Thing.SetTag("$FN_ASTRAL"); else if ( e.Thing.GetClassName() == "Annihilator" ) { e.Thing.SetTag("$FN_ANNIHIL"); // OH BOY, THESE AREN'T CHANGEABLE //e.Thing.Obituary = "$OB_ANNIHIL"; } else if ( e.Thing.GetClassName() == "FormerCaptain" ) { e.Thing.SetTag("$FN_FCAPTAIN"); //e.Thing.Obituary = "$OB_FCAPTAIN"; } else if ( e.Thing.GetClassName() == "NightmareDemon" ) { e.Thing.SetTag("$FN_NDEMON"); //e.Thing.Obituary = "$OB_NDEMON"; } // doom vacation stuff else if ( indoomvacation ) { if ( e.Thing.GetClassName() == "Babe" ) { e.Thing.bSHOOTABLE = false; // no hurt let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = .2; } else if ( e.Thing.GetClassName() == "CommanderKeen" ) { let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = .4; HeadpatTracker(hp).hdoomangfix = 5; } else if ( e.Thing.GetClassName() == "BBChair" ) { e.Thing.bUSESPECIAL = false; let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = .2; HeadpatTracker(hp).hdoomangfix = 15; HeadpatTracker(hp).patstate = e.Thing.MeleeState; } else if ( e.Thing.GetClassName() == "EvilEye" ) { let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = .1; } else if ( e.Thing.GetClassName() == "HeadCandles" ) { let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomangfix = 20; } else if ( e.Thing.GetClassName() == "HeartColumn" ) { let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = -.3; } else if ( e.Thing.GetClassName() == "Meat2" ) { let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = .6; HeadpatTracker(hp).hdoomangfix = -15; HeadpatTracker(hp).dvacationarghack = true; } else if ( e.Thing.GetClassName() == "Meat3" ) { let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = .6; HeadpatTracker(hp).hdoomangfix = 20; HeadpatTracker(hp).dvacationarghack = true; } else if ( e.Thing.GetClassName() == "LegsBabe" ) { let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = -1.5; HeadpatTracker(hp).hdoomangfix = 20; HeadpatTracker(hp).dvacationarghack = true; } else if ( e.Thing.GetClassName() == "Meat4" ) { let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; HeadpatTracker(hp).hdoomheightfix = .6; HeadpatTracker(hp).hdoomangfix = 15; HeadpatTracker(hp).dvacationarghack = true; } } if ( SWWMUtility.IdentifyingDog(e.Thing) || SWWMUtility.IdentifyingCaco(e.Thing) || SWWMUtility.IdentifyingDrug(e.Thing) || SWWMUtility.IdentifyingDoubleBoi(e.Thing) ) { // you can pet the dog, and you can also pet the caco (and friends) let hp = Actor.Spawn("HeadpatTracker",e.Thing.pos); hp.target = e.Thing; } SWWMCombatTracker trk; if ( !swwm_notrack && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER) && !(e.Thing is 'LampMoth') && !(e.Thing is 'CompanionLamp') ) trk = SWWMCombatTracker.Spawn(e.Thing); if ( !(e.Thing is 'LampMoth') && (e.Thing.bSHOOTABLE || e.Thing.bISMONSTER || e.Thing.bCORPSE || (e.Thing is 'Inventory') || (e.Thing is 'CompanionLamp')) ) { if ( (swwm_shadows == 2) || ((swwm_shadows == 1) && ((e.Thing is 'Demolitionist') || (e.Thing.SpawnState.sprite == e.Thing.GetSpriteIndex('XZW1')))) ) SWWMShadow.Track(e.Thing); } // Ynykron vortex optimization (faster than a thinker iterator) if ( e.Thing.bSHOOTABLE || e.Thing.bMISSILE ) SuckableActors.Push(e.Thing); // vanilla blood color changes if ( (e.Thing.GetClass() == "BaronOfHell") || (e.Thing.GetClass() == "HellKnight") || (e.Thing.GetClass() == "Bishop") || (e.Thing.GetClass() == "Korax") ) { let gb = Actor.Spawn("GreenBloodReference"); e.Thing.CopyBloodColor(gb); gb.Destroy(); } else if ( e.Thing.GetClass() == "Cacodemon" ) { let bb = Actor.Spawn("BlueBloodReference"); e.Thing.CopyBloodColor(bb); bb.Destroy(); } else if ( (e.Thing.GetClass() == "Wizard") || (e.Thing.GetClass() == "Heresiarch") || (e.Thing.GetClass() == "Sorcerer2") ) { let pb = Actor.Spawn("PurpleBloodReference"); e.Thing.CopyBloodColor(pb); pb.Destroy(); } else if ( e.Thing.GetClass() == "LostSoul" ) e.Thing.bNOBLOOD = true; // vanilla boss stuff bool upgrademe = swwm_upgradebosses; if ( bossmap == -1 ) bossmap = WhichVanillaBossMap(); if ( bossmap == MAP_DE1M8 ) { if ( e.Thing is 'BaronOfHell' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 3; if ( trk ) trk.bBOSS = true; } bosstag = "$BT_BRUISERS"; } else if ( bossmap == MAP_DE2M8 ) { if ( e.Thing is 'Cyberdemon' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 5; if ( trk ) trk.bBOSS = true; } bosstag = "$BT_CYBIE"; } else if ( bossmap == MAP_DE3M8 ) { if ( e.Thing is 'Spidermastermind' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 6; if ( trk ) trk.bBOSS = true; } bosstag = "$BT_SPIDER"; } else if ( bossmap == MAP_DE4M8 ) { if ( e.Thing is 'Spidermastermind' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 4; if ( trk ) trk.bBOSS = true; } bosstag = "$BT_SPIDER2"; } else if ( bossmap == MAP_DMAP07 ) { if ( (e.Thing is 'Fatso') || (e.Thing is 'Arachnotron') ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2; if ( trk ) trk.bBOSS = true; } bosstag = "$BT_DIMPLE"; } else if ( bossmap == MAP_DMAP30 ) { if ( e.Thing is 'BossBrain' ) { bossbrainactor = e.Thing; bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 40; // goodbye, instakills if ( trk ) trk.bBOSS = true; } if ( e.Thing is 'BossEye' ) bossviewactor = e.Thing; bosstag = "$BT_IOS"; } else if ( bossmap == MAP_HE1M8_HE4M8 ) { if ( e.Thing is 'IronLich' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 4; if ( trk ) trk.bBOSS = true; } bosstag = "$BT_LICHES"; } else if ( bossmap == MAP_HE2M8_HE5M8 ) { if ( e.Thing is 'Minotaur' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 3; if ( trk ) trk.bBOSS = true; } bosstag = "$BT_MINOTAUR"; } else if ( bossmap == MAP_HE3M8 ) { if ( e.Thing is 'Sorcerer1' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2; if ( trk ) trk.bBOSS = true; bosstag = "$BT_DSPARIL"; } else if ( e.Thing is 'Sorcerer2' ) { // second phase bossactors.Clear(); initialized = false; bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 8; if ( trk ) trk.bBOSS = true; bosstag = "$BT_DSPARIL2"; } } else if ( bossmap == MAP_HMAP38 ) { if ( e.Thing is 'ClericBoss' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2; if ( trk ) trk.bBOSS = true; bosstag = "$BT_CLERIC"; } } else if ( bossmap == MAP_HMAP36 ) { if ( e.Thing is 'FighterBoss' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2; if ( trk ) trk.bBOSS = true; bosstag = "$BT_FIGHTER"; } } else if ( bossmap == MAP_HMAP37 ) { if ( e.Thing is 'MageBoss' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2; if ( trk ) trk.bBOSS = true; bosstag = "$BT_MAGE"; } } else if ( bossmap == MAP_HMAP12 ) { if ( e.Thing is 'Dragon' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 4; if ( trk ) trk.bBOSS = true; bosstag = "$BT_DRAGON"; } } else if ( bossmap == MAP_HMAP23_HMAP27_HMAP48_HMAP55 ) { if ( e.Thing is 'Heresiarch' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 8; if ( trk ) trk.bBOSS = true; bosstag = "$BT_HERESIARCH"; } } else if ( bossmap == MAP_HMAP40 ) { if ( e.Thing is 'Korax' ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 10; if ( trk ) trk.bBOSS = true; bosstag = "$BT_KORAX"; } } else if ( bossmap == MAP_HMAP60 ) { if ( (e.Thing is 'FighterBoss') || (e.Thing is 'ClericBoss') || (e.Thing is 'MageBoss') ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 4; if ( trk ) trk.bBOSS = true; bosstag = "$BT_DEATHKINGS"; initialized = true; // healthbar shows from the start } } else if ( bossmap == MAP_EVMAP30 ) { if ( e.Thing.GetClassName() == "ArchangelusA" ) { bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 5; if ( trk ) trk.bBOSS = true; bosstag = "$BT_ARCHANGELUS"; } else if ( e.Thing.GetClassName() == "ArchangelusB" ) { // second phase bossactors.Clear(); initialized = false; bossactors.Push(e.Thing); if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 5; if ( trk ) trk.bBOSS = true; bosstag = "$BT_ARCHANGELUS"; } } // inflation check if ( trk ) { trk.maxhealth = trk.lasthealth = e.Thing.Health; trk.intp.Reset(trk.lasthealth); } } override void PostUiTick() { if ( (gametic == onelinertic) && (oneliner != "") && (players[consoleplayer].health > 0) ) { if ( onelinerlevel > swwm_mutevoice ) { let l = SWWMOneLiner.Make(oneliner,onelinerspan); StatusBar.AttachMessage(l,-3473); } SendNetworkEvent("swwmremotelinertxt."..oneliner,consoleplayer,onelinerlevel); } for ( int i=0; i 0 ) { cummdamage += curcumm; lastcummtic = gametic; } else if ( gametic > lastcummtic+150 ) cummdamage = 0; thealth = newhealth; ihealthr.Update(thealth); if ( thealth > oldhealth[29] ) for ( int i=29; i>0; i-- ) oldhealth[i] = thealth; ihealth.Update(oldhealth[29]); for ( int i=29; i>0; i-- ) oldhealth[i] = oldhealth[i-1]; if ( thealth > 0 ) bossalpha = min(3.,bossalpha+1./30.); else bossalpha = max(0,bossalpha-1./50.); } override bool InputProcess( InputEvent e ) { if ( (e.Type == InputEvent.TYPE_KeyDown) && (e.KeyChar >= 0x61) && (e.KeyChar <= 0x7A) ) { // cheat code handling String cht[] = { "swwmlodsofemone", "swwmdeeplore", "swwmfroggygang", "swwmforgetaboutit", // SWWM Platinum cheats "swwmimstuck", "swwmarmojumbo", "swwmdangimhealthy", "swwmwarriorofzaemonath", "swwmpowerparp", "swwmcannotseemyhands", "swwmreflectonme", "swwmgunzmeneeds", "swwmbloodrainsfromheaven", "swwmnotwannaboom", "swwmverywrappyoatmeal", "swwmflaggerybingo", "swwmheadsball", "swwmsmarties", "swwmnocilla", "swwmmarioisaweenie", "swwmpunish", "swwmboingball", "swwmgassy", "swwmiamsuperman", "swwmtouchstone" }; String cmd[] = { "swwmmoneycheat", "swwmlorecheat", "swwmfroggycheat", "swwmamnesiacheat", // SWWM Platinum cheats "swwmsafecheat", "swwmweaponcheat", "swwmhealcheat", "swwmynykroncheat", "swwmgravcheat", "swwminvischeat", "swwmbarriercheat", "swwmammocheat", "swwmbloodcheat", "swwmexplocheat", "swwmallcheat", "swwmflagcheat", "swwmballcheat", "swwmsmartcheat", "swwmnutcheat", "swwmweeniecheat", "swwmpunishcheat", "swwmball2cheat", "swwmfartcheat", "swwmsupercheat", "swwmstonecheat" }; bool matchany = false; kstr.AppendCharacter(e.KeyChar); if ( kstr.Length() > 0 ) { if ( kcode >= 4 ) S_StartSound("misc/boink",CHAN_WEAPON,CHANF_UI|CHANF_OVERLAP,pitch:FRandom[HudStuff](.8,1.2)); for ( int i=0; i= 4 ) { kfail = true; klinger = gametic+40; klingerstr = kstr; S_StartSound("bruh",CHAN_VOICE,CHANF_UI); eatit = true; } kcode = 0; kstr = ""; if ( eatit ) return true; } else { kcode++; if ( kcode > 4 ) return true; // eat keypresses from this point } } // F if ( e.KeyChar == 0x66 ) { let demo = Demolitionist(players[consoleplayer].mo); let gone = PlayerGone(players[consoleplayer].mo); if ( (demo && (demo.Health <= 0) && (demo.deadtimer > 40)) || (gone && (gone.Health <= 0) && (gone.deadtimer > 40)) ) { // pay respects int numf = Random[FInTheChat](1,6); for ( int i=0; i 255) ) return; if ( e.Thing.CheckLocalView() && !e.Thing.CheckKeys(locknum,false,true) ) { if ( !lastlock || (gametic > lastlock+20) ) { if ( SWWMUtility.IsValidLockNum(locknum) ) lastlock = AddOneliner("locked",2); else lastlock = AddOneliner("jammed",2); } } } override void WorldLineActivated( WorldEvent e ) { if ( !(e.ActivationType&SPAC_Use) ) return; if ( !e.Thing || !e.Thing.player ) return; let w = SWWMWeapon(e.Thing.player.ReadyWeapon); if ( !w || !w.wallponch ) return; let s = SWWMStats.Find(e.Thing.player); if ( s ) s.wponch++; } override void CheckReplacee( ReplacedEvent e ) { if ( e.Replacement is 'DSparilHax' ) e.Replacee = 'Sorcerer2'; } private Class GetDRLAReplacement( Class a ) { static const String refpool[] = { "Zombieman", "Shotgunguy", "Chaingunguy", "DoomImp", "Demon", "Spectre", "LostSoul", "Cacodemon", "HellKnight", "BaronOfHell", "Arachnotron", "PainElemental", "Revenant", "Fatso", "Archvile", "Cyberdemon", "SpiderMastermind", "BossEye", "BossBrain" }; static const String babypool[] = { "RLFormerHumanPistol", "RLFormerSergeantShotgun", "RLFormerCommandoChaingun", "RLImp", "RLDemon", "RLSpectre", "RLLostSoul", "RLCacodemon", "RLHellKnight", "RLBaronOfHell", "RLArachnotron", "RLPainElemental", "RLRevenant", "RLMancubus", "RLArchvile", "RLCyberdemon", "RLSpiderMastermindVariantSpawner", "RLEasyBossEye", "RLBossBrain" }; static const String easypool[] = { "RLFormerHumanNoArmageddonSpawner", "RLFormerSergeantNoArmageddonSpawner", "RLFormerCommandoNoArmageddonSpawner", "RLImpNoArmageddonSpawner", "RLDemonNoArmageddonSpawner", "RLSpectreNoArmageddonSpawner", "RLLostSoulNoArmageddonSpawner", "RLCacodemonNoArmageddonSpawner", "RLHellKnightNoArmageddonSpawner", "RLBaronOfHellNoArmageddonSpawner", "RLArachnotronNoArmageddonSpawner", "RLPainElementalNoArmageddonSpawner", "RLRevenantNoArmageddonSpawner", "RLMancubusNoArmageddonSpawner", "RLArchvileNoArmageddonSpawner", "RLCyberdemonNoArmageddonSpawner", "RLSpiderMastermindNoArmageddonSpawner", "RLBossEye", "RLBossBrain" }; static const String normalpool[] = { "RLFormerHumanNoArmageddonSpawner", "RLFormerSergeantNoArmageddonSpawner", "RLFormerCommandoNoArmageddonSpawner", "RLImpNoArmageddonSpawner", "RLDemonNoArmageddonSpawner", "RLSpectreNoArmageddonSpawner", "RLLostSoulNoArmageddonSpawner", "RLCacodemonNoArmageddonSpawner", "RLHellKnightNoArmageddonSpawner", "RLBaronOfHellNoArmageddonSpawner", "RLArachnotronNoArmageddonSpawner", "RLPainElementalNoArmageddonSpawner", "RLRevenantNoArmageddonSpawner", "RLMancubusNoArmageddonSpawner", "RLArchvileNoArmageddonSpawner", "RLCyberdemonNoArmageddonSpawner", "RLSpiderMastermindNoArmageddonSpawner", "RLBossEye", "RLBossBrain" }; static const String hardpool[] = { "RLFormerHumanSpawner", "RLFormerSergeantSpawner", "RLFormerCommandoSpawner", "RLImpSpawner", "RLDemonSpawner", "RLSpectreSpawner", "RLLostSoulSpawner", "RLCacodemonSpawner", "RLHellKnightSpawner", "RLBaronOfHellSpawner", "RLArachnotronSpawner", "RLPainElementalSpawner", "RLRevenantSpawner", "RLMancubusSpawner", "RLArchvileSpawner", "RLCyberdemonSpawner", "RLSpiderMastermindSpawner", "RLUVBossEye", "RLBossBrain" }; static const String nightmarepool[] = { "RLEliteFormerHumanSpawner", "RLEliteFormerSergeantSpawner", "RLEliteFormerCommandoSpawner", "RLNightmareImp", "RLNightmareDemon", "RLNightmareSpectre", "RLNightmareLostSoul", "RLNightmareCacodemon", "RLNightmareHellKnight", "RLNightmareBaronOfHell", "RLNightmareArachnotron", "RLNightmarePainElemental", "RLNightmareRevenant", "RLNightmareMancubus", "RLNightmareArchvile", "RLNightmareCyberdemonSpawner", "RLNightmareSpiderMastermindSpawner", "RLNightmareBossEye", "RLNightmareBossBrain" }; static const String technophobiapool[] = { "RLFormerCyborgBattleRifle", "RLFormerCyborgBattleRifle", "RLFormerCyborgBattleRifle", "RLCyberneticImp", "RLCyberneticDemon", "RLCyberneticSpectre", "RLCyberneticLostSoul", "RLCacodemon", "RLCyberneticHellKnight", "RLCyberneticBaronOfHell", "RLCyberneticArachnotron", "RLCyberneticPainElemental", "RLCyberneticRevenant", "RLCyberneticMancubus", "RLCyberneticArchvile", "RLCyberneticCyberdemonSpawner", "RLCyberneticSpiderMastermindSpawner", "RLTechnophobiaBossEye", "RLTechnophobiaBossBrain" }; static const String armageddonpool[] = { "RLFormerAssaultTrooper", "RLFormerOverwatch", "RLFormerShocktrooper", "RLArmageddonImp", "RLArmageddonDemon", "RLArmageddonSpectreSpawner", "RLTheHungrySpawner", "RLArmageddonCacodemon", "RLArmageddonHellKnightSpawner", "RLArmageddonBaronOfHell", "RLArmageddonArachnotron", "RLArmageddonPainElemental", "RLArmageddonRevenant", "RLArmageddonMancubus", "RLArmageddonArchvileSpawner", "RLArmageddonCyberdemonSpawner", "RLArmageddonSpiderMastermindSpawner", "RLArmageddonBossEye", "RLArmageddonBossBrain" }; static const String adaptivepool[] = { "RLAdaptiveFormerHuman", "RLAdaptiveFormerSergeant", "RLAdaptiveFormerCommando", "RLAdaptiveImp", "RLAdaptiveDemon", "RLAdaptiveSpectre", "RLAdaptiveLostSoul", "RLAdaptiveCacodemon", "RLAdaptiveHellKnight", "RLAdaptiveBaronOfHell", "RLAdaptiveArachnotron", "RLAdaptivePainElemental", "RLAdaptiveRevenant", "RLAdaptiveMancubus", "RLAdaptiveArchvile", "RLAdaptiveCyberdemon", "RLAdaptiveSpiderMastermind", "RLUVBossEye", "RLBossBrain" }; switch ( swwm_drlaskill ) { case 0: for ( int i=0; i<18; i++ ) { if ( !(a is refpool[i]) ) continue; return babypool[i]; } break; case 1: for ( int i=0; i<18; i++ ) { if ( !(a is refpool[i]) ) continue; return easypool[i]; } break; case 2: for ( int i=0; i<18; i++ ) { if ( !(a is refpool[i]) ) continue; return normalpool[i]; } break; case 3: for ( int i=0; i<18; i++ ) { if ( !(a is refpool[i]) ) continue; return hardpool[i]; } break; case 4: for ( int i=0; i<18; i++ ) { if ( !(a is refpool[i]) ) continue; return nightmarepool[i]; } break; case 5: for ( int i=0; i<18; i++ ) { if ( !(a is refpool[i]) ) continue; return technophobiapool[i]; } break; case 6: for ( int i=0; i<18; i++ ) { if ( !(a is refpool[i]) ) continue; return armageddonpool[i]; } break; case 7: default: for ( int i=0; i<18; i++ ) { if ( !(a is refpool[i]) ) continue; return adaptivepool[i]; } break; } return null; } override void CheckReplacement( ReplaceEvent e ) { // respect final replacements if ( e.IsFinal ) return; // shell types (sorted by rarity static const Class redpool[] = {"RedShell","RedShell2","RedShell4"}; static const Class greenpool[] = {"GreenShell","GreenShell2","GreenShell4"}; static const Class whitepool[] = {"WhiteShell","WhiteShell2"}; static const Class purplepool[] = {"PurpleShell","PurpleShell2","PurpleShell4"}; static const Class bluepool[] = {"BlueShell","BlueShell2","BlueShell4"}; static const Class blackpool[] = {"BlackShell","BlackShell2"}; // DRLA Monsters stuff if ( hasdrlamonsters ) { let rep = GetDRLAReplacement(e.Replacee); if ( rep ) { e.Replacement = rep; e.IsFinal = true; return; } } // only replace vanilla blood if no other gore mod is doing it if ( (e.Replacee == "Blood") && (!e.Replacement || e.Replacement == "Blood") && swwm_blood ) e.Replacement = "mkBlood"; else if ( e.Replacee is 'ItemFog' ) e.Replacement = 'SWWMItemFog'; else if ( e.Replacee is 'TeleportFog' ) e.Replacement = 'SWWMTeleportFog'; else if ( (e.Replacee is 'CommanderKeen') && (!e.Replacement || (e.Replacement == 'CommanderKeen')) ) { let def = GetDefaultByType(e.Replacee); bool dehackery = false; for ( State s=def.SpawnState; s; s=s.NextState ) { if ( s.bDEHACKED ) dehackery = true; // keep checking until we hit a loop, just in case if ( s.NextState && (s.DistanceTo(s.NextState) <= 0) ) break; } if ( dehackery ) return; e.Replacement = 'SWWMHangingKeen'; } else if ( (e.Replacee is 'BossBrain') && (!e.Replacement || (e.Replacement == 'BossBrain')) ) { let def = GetDefaultByType(e.Replacee); bool dehackery = false; for ( State s=def.SpawnState; s; s=s.NextState ) { if ( s.bDEHACKED ) dehackery = true; // keep checking until we hit a loop, just in case if ( s.NextState && (s.DistanceTo(s.NextState) <= 0) ) break; } if ( dehackery ) return; e.Replacement = 'SWWMBossBrain'; } else if ( e.Replacee is 'RedCard' ) { if ( level.GetChecksum() ~== "3805A661D5C4523AFF7BF86991071043" ) return; // don't replace red key in Equinox MAP13 e.Replacement = 'SWWMRedCard'; } else if ( e.Replacee is 'BlueCard' ) e.Replacement = 'SWWMBlueCard'; else if ( e.Replacee is 'YellowCard' ) e.Replacement = 'SWWMYellowCard'; else if ( e.Replacee.GetClassName() == 'KDiZDSilverKey' ) e.Replacement = 'SWWMSilverCardKDiZD'; else if ( e.Replacee.GetClassName() == 'KDiZDGreenKey' ) e.Replacement = 'SWWMGreenCardKDiZD'; else if ( e.Replacee.GetClassName() == 'KDiZDOrangeKey' ) e.Replacement = 'SWWMOrangeCardKDiZD'; else if ( e.Replacee.GetClassName() == 'GreenCard' ) e.Replacement = 'SWWMGreenCard'; else if ( e.Replacee is 'RedSkull' ) e.Replacement = 'SWWMRedSkull'; else if ( e.Replacee is 'BlueSkull' ) e.Replacement = 'SWWMBlueSkull'; else if ( e.Replacee is 'YellowSkull' ) e.Replacement = 'SWWMYellowSkull'; else if ( e.Replacee is 'KeyGreen' ) e.Replacement = 'SWWMKeyGreen'; else if ( e.Replacee is 'KeyBlue' ) e.Replacement = 'SWWMKeyBlue'; else if ( e.Replacee is 'KeyYellow' ) e.Replacement = 'SWWMKeyYellow'; else if ( e.Replacee.GetClassName() == 'KeyRed' ) e.Replacement = 'SWWMKeyRed'; else if ( (e.Replacee is 'Chainsaw') || (e.Replacee is 'Gauntlets') || (e.Replacee is 'FWeapAxe') ) e.Replacement = SWWMUtility.PickSWWMSlot1(); else if ( (e.Replacee is 'Fist') || (e.Replacee is 'Staff') ) e.Replacement = 'DeepImpact'; else if ( (e.Replacee is 'Pistol') || (e.Replacee is 'GoldWand') || (e.Replacee is 'FWeapFist') || (e.Replacee is 'CWeapMace') || (e.Replacee is 'MWeapWand') || (e.Replacee.GetClassName() == 'TangoPistol') ) e.Replacement = SWWMUtility.PickSWWMSlot2(); else if ( (e.Replacee is 'Shotgun') || (e.Replacee is 'CWeapStaff') || (e.Replacee.GetClassName() == 'TangoShotgun') ) e.Replacement = SWWMUtility.IsDoomOne()?SWWMUtility.PickHereticSlot3():SWWMUtility.PickSWWMSlot3(); else if ( (e.Replacee is 'SuperShotgun') || (e.Replacee is 'MWeapFrost') || (e.Replacee.GetClassName() == 'TangoSuperShotgun') ) e.Replacement = SWWMUtility.PickSWWMSlot4(); else if ( (e.Replacee is 'Crossbow') || (e.Replacee.GetClassName() == 'TangoScrapGun') ) e.Replacement = SWWMUtility.PickHereticSlot3(); else if ( (e.Replacee is 'Chaingun') || (e.Replacee is 'Blaster') || (e.Replacee is 'FWeaponPiece3') || (e.Replacee.GetClassName() == 'TangoAssaultRifle') || (e.Replacee.GetClassName() == 'TangoChaingun') ) e.Replacement = SWWMUtility.PickSWWMSlot5(); else if ( (e.Replacee is 'RocketLauncher') || (e.Replacee is 'PhoenixRod') || (e.Replacee is 'FWeapHammer') || (e.Replacee.GetClassName() == 'TangoStomper') ) e.Replacement = SWWMUtility.PickSWWMSlot6(); else if ( (e.Replacee is 'PlasmaRifle') || (e.Replacee is 'SkullRod') ) e.Replacement = SWWMUtility.PickDoomSlot6(); else if ( e.Replacee is 'CWeapFlame' ) e.Replacement = SWWMUtility.PickSWWMSlot7(); else if ( e.Replacee is 'MWeapLightning' ) e.Replacement = SWWMUtility.PickSWWMSlot8(); else if ( (e.Replacee is 'BFG9000') || (e.Replacee is 'Mace') ) e.Replacement = SWWMUtility.PickDoomSlot7(); else if ( e.Replacee is 'CWeaponPiece2' ) e.Replacement = SWWMUtility.PickSWWMSlot9(); else if ( e.Replacee is 'MWeaponPiece1' ) e.Replacement = SWWMUtility.PickSWWMSlot0(); else if ( (e.Replacee is 'ShellBox') || (e.Replacee is 'CrossbowHefty') || (e.Replacee.GetClassName() == 'TangoShellBox') || (e.Replacee.GetClassName() == 'TangoScrapDrumPack') ) { /*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SMW05SmallAmmo':'SMW05BigAmmo'; else */switch( Random[Replacements](0,14) ) { case 0: case 1: case 2: e.Replacement = redpool[Random[Replacements](1,2)]; break; case 3: case 4: case 5: e.Replacement = greenpool[Random[Replacements](1,2)]; break; case 6: case 7: case 8: e.Replacement = whitepool[Random[Replacements](0,1)]; break; case 9: case 10: case 11: e.Replacement = purplepool[Random[Replacements](0,2)]; break; case 12: case 13: e.Replacement = bluepool[Random[Replacements](0,2)]; break; case 14: e.Replacement = blackpool[Random[Replacements](0,1)]; break; } } else if ( (e.Replacee is 'Shell') || (e.Replacee is 'CrossbowAmmo') || (e.Replacee.GetClassName() == 'TangoShell') || (e.Replacee.GetClassName() == 'TangoScrapDrum') ) { /*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SMW05SmallAmmo':'SMW05BundleSpawn'; else */switch( Random[Replacements](0,13) ) { case 0: case 1: case 2: e.Replacement = redpool[Random[Replacements](0,1)]; break; case 3: case 4: case 5: e.Replacement = greenpool[Random[Replacements](0,1)]; break; case 6: case 7: e.Replacement = whitepool[0]; break; case 8: case 9: case 10: e.Replacement = purplepool[Random[Replacements](0,1)]; break; case 11: case 12: e.Replacement = bluepool[Random[Replacements](0,1)]; break; case 13: e.Replacement = blackpool[0]; break; } } else if ( e.Replacee is 'ClipBox' ) { /*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SheenSmallAmmo':'SheenBigAmmo'; else */e.Replacement = Random[Replacements](0,4)?'EvisceratorShell':Random[Replacements](0,6)?'EvisceratorTrioSpawn':'EvisceratorSixPack'; } else if ( (e.Replacee is 'Clip') || (e.Replacee is 'GoldWandAmmo') ) e.Replacement = /*(e.Replacee is 'GoldWandHefty')?'SheenSmallAmmo':'SheenTinyAmmo'*/'SWWMNothing'; else if ( e.Replacee is 'BlasterHefty' ) { /*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SheenBigAmmo':'SheenSmallAmmo'; else */e.Replacement = Random[Replacements](0,6)?'EvisceratorTrioSpawn':'EvisceratorSixPack'; } else if ( (e.Replacee is 'BlasterAmmo') || (e.Replacee.GetClassName() == 'TangoBulletClipHalf') ) { /*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SheenSmallAmmo':'SheenTinyAmmo'; else */e.Replacement = 'EvisceratorShell'; } else if ( (e.Replacee is 'RocketBox') || (e.Replacee is 'PhoenixRodHefty') || (e.Replacee is 'MaceHefty')|| (e.Replacee.GetClassName() == 'TangoStomperBox') ) { /*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'QuadravolAmmo':'QuadravolAmmoBundleSpawn'; else */switch ( Random[Replacements](0,11) ) { case 0: case 1: case 2: case 3: case 4: if ( Random[Replacements](0,5) ) e.Replacement = 'HellblazerMissiles'; else if ( Random[Replacements](0,4) ) e.Replacement = 'HellblazerMissileTrioSpawn'; else e.Replacement = 'HellblazerMissileMag'; break; case 5: case 6: case 7: case 8: if ( Random[Replacements](0,6) ) e.Replacement = 'HellblazerCrackshots'; else e.Replacement = 'HellblazerCrackshotMag'; break; case 9: case 10: if ( Random[Replacements](0,8) ) e.Replacement = 'HellblazerRavagers'; else e.Replacement = 'HellblazerRavagerMag'; break; case 11: if ( Random[Replacements](0,10) ) e.Replacement = 'HellblazerWarheads'; else e.Replacement = 'HellblazerWarheadMag'; break; } } else if ( (e.Replacee is 'RocketAmmo') || (e.Replacee is 'PhoenixRodAmmo') || (e.Replacee is 'MaceAmmo') || (e.Replacee.GetClassName() == 'TangoStomperAmmo') ) { /*if ( Random[Replacements](0,1) ) e.Replacement = 'QuadravolAmmo'; else */e.Replacement = Random[Replacements](0,2)?'HellblazerMissiles':'HellblazerCrackshots'; } else if ( (e.Replacee is 'CellPack') || (e.Replacee is 'SkullRodHefty') ) { /*if ( Random[Replacements](0,1) ) { if ( !Random[Replacements](0,2) ) e.Replacement = Random[Replacements](0,3)?'EMPCoreBundleSpawn':'EMPCore'; else if ( Random[Replacements](0,2) ) e.Replacement = 'RayBoltBundleSpawn'; else e.Replacement = 'RayAmmo'; } else */if ( !Random[Replacements](0,2) ) { if ( Random[Replacements](0,3) ) e.Replacement = Random[Replacements](0,2)?'SilverBulletsBundleSpawn':'SilverBullets2BundleSpawn'; else e.Replacement = Random[Replacements](0,2)?'SilverBulletAmmo':'SilverBulletAmmo2'; } else if ( Random[Replacements](0,2) ) e.Replacement = 'CandyGunBulletsBundleSpawn'; else e.Replacement = 'CandyGunAmmo'; } else if ( (e.Replacee is 'Cell') || (e.Replacee is 'SkullRodAmmo') ) { if ( !Random[Replacements](0,2) ) e.Replacement = /*!Random[Replacements](0,2)?'RayBattery':*/Random[Replacements](0,2)?'HellblazerRavagers':'HellblazerWarheads'; else if ( Random[Replacements](0,2) ) e.Replacement = /*Random[Replacements](0,1)?'DarkCanister':*/'SparkUnit'; else if ( !Random[Replacements](0,3) ) e.Replacement = /*Random[Replacements](0,1)?'RayBolt':*/'CandyGunBullets'; else e.Replacement = /*Random[Replacements](0,1)?'EMPCore':*/Random[Replacements](0,2)?'SilverBullets':'SilverBullets2'; } else if ( e.Replacee is 'Mana1' ) e.Replacement = 'FabricatorTier1'; else if ( e.Replacee is 'Mana2' ) e.Replacement = 'FabricatorTier2'; else if ( e.Replacee is 'Mana3' ) e.Replacement = 'FabricatorTier3'; else if ( e.Replacee is 'ArtiBoostMana' ) e.Replacement = 'FabricatorTier4'; else if ( (e.Replacee is 'Backpack') || (e.Replacee is 'BagOfHolding') || (e.Replacee is 'ArtiPork') ) e.Replacement = 'HammerspaceEmbiggener'; else if ( (e.Replacee is 'FWeaponPiece1') || (e.Replacee is 'FWeaponPiece2') || (e.Replacee is 'CWeaponPiece1') || (e.Replacee is 'CWeaponPiece3') || (e.Replacee is 'MWeaponPiece2') || (e.Replacee is 'MWeaponPiece3') ) e.Replacement = 'SWWMNothing'; else if ( e.Replacee is 'ArmorBonus' ) e.Replacement = 'ArmorNuggetItem'; else if ( e.Replacee is 'HealthBonus' ) e.Replacement = 'HealthNuggetItem'; else if ( (e.Replacee is 'ArtiTimeBomb') || (e.Replacee is 'ArtiBlastRadius') || (e.Replacee is 'ArtiPoisonBag') || (e.Replacee is 'ArtiHealingRadius') ) e.Replacement = (nugflip=!nugflip)?'HealthNuggetBundleSpawn':'ArmorNuggetBundleSpawn'; else if ( (e.Replacee is 'HealthBonus') ) e.Replacement = 'HealthNuggetItem'; else if ( (e.Replacee is 'Stimpack') || (e.Replacee is 'CrystalVial') ) e.Replacement = 'TetraHealthItem'; else if ( (e.Replacee is 'Medikit') || (e.Replacee is 'ArtiHealth') ) e.Replacement = 'CubeHealthItem'; else if ( (e.Replacee is 'Soulsphere') || (e.Replacee is 'ArtiSuperHealth') ) e.Replacement = 'RefresherItem'; else if ( (e.Replacee is 'Megasphere') || (e.Replacee is 'ArtiEgg') || (e.Replacee is 'ArtiBoostArmor') ) e.Replacement = 'GrilledCheeseSandwich'; else if ( (e.Replacee is 'Blursphere') || (e.Replacee is 'ArtiInvisibility') ) e.Replacement = 'GhostArtifact'; else if ( e.Replacee is 'Radsuit' ) e.Replacement = 'EBarrier'; else if ( (e.Replacee is 'ArtiFly') ) e.Replacement = 'GravitySuppressor'; else if ( (e.Replacee is 'InvulnerabilitySphere') || (e.Replacee is 'ArtiInvulnerability') || (e.Replacee is 'ArtiInvulnerability2') ) e.Replacement = 'FuckingInvinciball'; else if ( (e.Replacee is 'Berserk') || (e.Replacee == 'ArtiTomeOfPower') || (e.Replacee == 'ArtiSpeedBoots') ) e.Replacement = 'Ragekit'; else if ( (e.Replacee is 'AllMap') || (e.Replacee is 'SuperMap') ) e.Replacement = 'Omnisight'; else if ( (e.Replacee is 'Infrared') || (e.Replacee is 'ArtiTorch') ) e.Replacement = 'SWWMLamp'; else if ( (e.Replacee is 'GreenArmor') || (e.Replacee is 'SilverShield') || (e.Replacee is 'PlatinumHelm') || (e.Replacee is 'AmuletOfWarding') ) e.Replacement = 'BlastSuitItem'; else if ( (e.Replacee is 'BlueArmor') || (e.Replacee is 'EnchantedShield') || (e.Replacee is 'MeshArmor') || (e.Replacee is 'FalconShield') ) e.Replacement = 'WarArmorItem'; else if ( (e.Replacee is 'ArtiDarkServant') || (e.Replacee == 'ArtiTeleportOther') ) e.Replacement = 'ChanceboxSpawner'; else if ( e.Replacee is 'ArtiTeleport' ) e.Replacement = (gameinfo.GameType&GAME_Hexen)?'ChanceboxSpawner':'SWWMNothing'; else return; // this last part is kind of ugly, but it works // guarantees that OUR replacements are all final e.IsFinal = true; } override void ConsoleProcess( ConsoleEvent e ) { // doing it with an event because this way we can control WHEN it should be openable if ( e.Name ~== "swwmdemomenu" ) { if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') ) return; Menu.SetMenu('DemolitionistMenu'); } else if ( e.Name ~== "swwmzoomin" ) { if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') ) return; double val = max(.5,swwm_mm_zoom/2.); CVar.FindCVar('swwm_mm_zoom').SetFloat(val); } else if ( e.Name ~== "swwmzoomout" ) { if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') ) return; double maxval = players[consoleplayer].mo.FindInventory("Omnisight")?2.:1.; double val = min(maxval,swwm_mm_zoom*2.); CVar.FindCVar('swwm_mm_zoom').SetFloat(val); } } override void NetworkProcess( ConsoleEvent e ) { static const Class cbttypes[] = {"RedShell","GreenShell","BlueShell","PurpleShell"}; if ( e.Name ~== "swwmgesture" ) { if ( (e.player == -1) || !playeringame[e.player] || !players[e.player].mo ) return; let mo = players[e.player].mo; switch( e.Args[0] ) { case 0: SWWMGesture.SetGesture(mo,GS_Wave); break; case 1: SWWMGesture.SetGesture(mo,GS_ThumbsUp); break; case 2: SWWMGesture.SetGesture(mo,GS_Victory); break; case 3: SWWMGesture.SetGesture(mo,GS_BlowKiss); break; } return; } else if ( e.Name ~== "swwmfixitemcaps" ) { // this command is only really needed when I update item max amounts mid-playthrough if ( multiplayer && (e.player != Net_Arbitrator) ) { if ( e.player == consoleplayer ) Console.Printf("Only the net arbitrator can call this event."); return; } for ( int i=0; i %d)",hams.GetTag(),hams.MaxAmount,hams.default.MaxAmount); hams.MaxAmount = hams.default.MaxAmount; hams.Amount = min(hams.Amount,hams.MaxAmount); } for ( Inventory inv=mo.inv; inv; inv=inv.inv ) { if ( inv is 'Ammo' ) { Ammo(inv).BackpackMaxAmount = Ammo(inv).default.BackpackMaxAmount; int newmax = inv.default.MaxAmount; if ( (hams.Amount > 0) && (Ammo(inv).BackpackMaxAmount > 0) ) { double factor = (Ammo(inv).BackpackMaxAmount-inv.default.MaxAmount)/double(hams.MaxAmount); newmax = int(inv.default.MaxAmount+hams.Amount*factor); } if ( inv.MaxAmount != newmax ) Console.Printf("Adjust %s capacity (%d -> %d)",inv.GetTag(),inv.MaxAmount,newmax); int dropme = max(0,inv.Amount-newmax); if ( dropme ) { Console.Printf("Dropped %dx %s.",dropme,inv.GetTag()); // non-SWWM ammos won't subdivide, but whatever, this is a debug command inv.CreateTossable(dropme); } inv.MaxAmount = newmax; } else if ( inv is 'MagAmmo' ) { if ( inv.MaxAmount != inv.default.MaxAmount ) Console.Printf("Adjust %s capacity (%d -> %d)",inv.GetTag(),inv.MaxAmount,inv.default.MaxAmount); // just drop the extras int dropme = max(0,inv.Amount-inv.default.MaxAmount); if ( dropme ) { Console.Printf("Dropped %dx %s.",dropme,inv.GetTag()); inv.CreateTossable(dropme); } inv.MaxAmount = inv.default.MaxAmount; } else { if ( inv.MaxAmount != inv.default.MaxAmount ) Console.Printf("Adjust %s capacity (%d -> %d)",inv.GetTag(),inv.MaxAmount,inv.default.MaxAmount); // only drop droppables (obviously) if ( !inv.bUNDROPPABLE && !inv.bUNTOSSABLE ) { int dropme = max(0,inv.Amount-inv.default.MaxAmount); if ( dropme ) { Console.Printf("Dropped %dx %s.",dropme,inv.GetTag()); for ( int j=0; j item = e.Name.Mid(14); if ( !item ) return; if ( SWWMCredits.Take(players[e.Args[0]],e.Args[1]) ) { let def = GetDefaultByType(item); SWWMWeapon sw; // drop the swapweapon if we own it first if ( swwm_swapweapons && (item is 'SWWMWeapon') && (sw = SWWMWeapon(def).HasSwapWeapon(players[e.Args[0]].mo)) ) { bool swapto = (sw == players[e.Args[0]].ReadyWeapon) || (sw.SisterWeapon && (sw.Sisterweapon == players[e.Args[0]].ReadyWeapon)); int ngun = sw.Amount; double ang = -15*(ngun-1); for ( int i=0; i 1) ) players[e.Args[0]].mo.A_SelectWeapon("DualExplodiumGun"); else players[e.Args[0]].mo.A_SelectWeapon((Class)(item)); } } } else if ( e.Name.Left(14) ~== "swwmstoretake." ) { Class item = e.Name.Mid(14); if ( !item ) return; int amt = e.Args[2]; if ( item is 'CandyGun' ) { // check if we can sell a spare instead, for the same price int n = players[e.Args[0]].mo.CountInv('CandyGunSpares'); if ( n >= amt ) { players[e.Args[0]].mo.TakeInventory('CandyGunSpares',amt); SWWMCredits.Give(players[e.Args[0]],e.Args[1]); return; } } // if player currently has the dual wield weapon selected, switch over if ( item is 'SWWMWeapon' ) { let c = Weapon(players[e.Args[0]].mo.FindInventory(item)); if ( c.SisterWeapon && (players[e.Args[0]].ReadyWeapon == c.SisterWeapon) ) { players[e.Args[0]].ReadyWeapon = c; players[e.Args[0]].SetPSprite(PSP_WEAPON,c.FindState("Ready")); players[e.Args[0]].SetPSprite(PSP_WEAPON+1,null); // delete left weapon psprite } } // if we're selling an embiggener, we need to readjust ammo if ( item is 'HammerspaceEmbiggener' ) { let ritm = players[e.Args[0]].mo.FindInventory(item); for ( Inventory i=players[e.Args[0]].mo.Inv; i; i=i.Inv ) { if ( !(i is 'Ammo') ) continue; if ( Ammo(i).BackpackMaxAmount > 0 ) { double factor = (Ammo(i).BackpackMaxAmount-i.default.MaxAmount)/double(ritm.MaxAmount); i.MaxAmount = int(i.default.MaxAmount+(ritm.Amount-amt)*factor); } // drop excess ammo int excess = i.Amount-i.MaxAmount; if ( excess > 0 ) i.CreateTossable(excess); } } players[e.Args[0]].mo.TakeInventory(item,amt); SWWMCredits.Give(players[e.Args[0]],e.Args[1]); } else if ( e.Name.Left(10) ~== "swwmtrade." ) { Class item = e.Name.Mid(10); if ( !item ) return; let def = GetDefaultByType(item); int amt = def.Amount; // if it's an ammo, check the largest unit givable if ( item is 'Ammo' ) { for ( int i=0; i)(AllActorClasses[i]); if ( !a || (a.GetParentClass() != item) || (GetDefaultByType(a).Amount < amt) ) continue; amt = GetDefaultByType(a).Amount; } } Inventory ritm = players[e.Args[1]].mo.FindInventory(item); if ( ritm ) { int maxgive = ritm.MaxAmount-ritm.Amount; if ( amt > maxgive ) amt = maxgive; } else if ( amt > def.MaxAmount ) amt = def.MaxAmount; bool rslt = false; Class giveitem = item; if ( item is 'HammerspaceEmbiggener' ) giveitem = 'TradedHammerspaceEmbiggener'; if ( (amt > 0) && players[e.Args[1]].mo.GiveInventory(giveitem,amt,true) ) { // if player currently has the dual wield weapon selected, switch over if ( item is 'SWWMWeapon' ) { let c = Weapon(players[e.Args[0]].mo.FindInventory(item)); if ( c.SisterWeapon && (players[e.Args[0]].ReadyWeapon == c.SisterWeapon) ) { players[e.Args[0]].ReadyWeapon = c; players[e.Args[0]].SetPSprite(PSP_WEAPON,c.FindState("Ready")); players[e.Args[0]].SetPSprite(PSP_WEAPON+1,null); // delete left weapon psprite } } // if we're trading an embiggener, we need to readjust ammo if ( item is 'HammerspaceEmbiggener' ) { let ritm = players[e.Args[0]].mo.FindInventory(item); for ( Inventory i=players[e.Args[0]].mo.Inv; i; i=i.Inv ) { if ( !(i is 'Ammo') ) continue; if ( Ammo(i).BackpackMaxAmount > 0 ) { double factor = (Ammo(i).BackpackMaxAmount-i.default.MaxAmount)/double(ritm.MaxAmount); i.MaxAmount = int(i.default.MaxAmount+(ritm.Amount-amt)*factor); } // drop excess ammo int excess = i.Amount-i.MaxAmount; if ( excess > 0 ) i.CreateTossable(excess); } } if ( item is 'CandyGun' ) { // see if we can take a fully loaded spare from us instead int n = players[e.Args[0]].mo.CountInv('CandyGunSpares'); int na = players[e.Args[0]].mo.CountInv('CandyGunAmmo'); if ( (n >= amt) && (na >= amt) ) { players[e.Args[0]].mo.TakeInventory('CandyGunSpares',amt); players[e.Args[0]].mo.TakeInventory('CandyGunAmmo',amt); } else players[e.Args[0]].mo.TakeInventory('CandyGun',amt); } else players[e.Args[0]].mo.TakeInventory(item,amt); // add to history SWWMTradeHistory.RegisterSend(players[e.Args[0]],players[e.Args[1]],item,amt); SWWMTradeHistory.RegisterReceive(players[e.Args[1]],players[e.Args[0]],item,amt); // 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." ) { let l = SWWMLoreLibrary.Find(players[e.Args[0]]); let idx = l.FindEntry(e.Name.Mid(17)); l.MarkRead(idx); } else if ( e.Name.Left(12) ~== "swwmuseitem." ) { Class item = e.Name.Mid(12); if ( !item ) return; let i = players[e.Args[0]].mo.FindInventory(item); if ( !i ) return; 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)); // dual wield gun support if ( (i is 'ExplodiumGun') && (players[e.Args[0]].PendingWeapon==Weapon(i).SisterWeapon) ) t.result = true; } else t.result = rslt; t.used = item; t.usedup = (!i||(i.Amount<=0)); checklist.Push(t); } } else if ( e.Name.Left(13) ~== "swwmdropitem." ) { Class item = e.Name.Mid(13); if ( !item ) return; let i = players[e.Args[0]].mo.FindInventory(item); if ( !i ) return; int amt = i.default.Amount; // if it's an ammo, check the largest unit givable if ( i is 'Ammo' ) { for ( int i=0; i)(AllActorClasses[i]); if ( !a || (a.GetParentClass() != item) || (GetDefaultByType(a).Amount < amt) ) continue; amt = GetDefaultByType(a).Amount; } } if ( amt > i.Amount ) amt = i.Amount; 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" ) { if ( consoleplayer != e.Args[1] ) return; switch ( e.Args[0] ) { case 0: AddOneliner("koraxgreet",3,60); break; case 1: AddOneliner("koraxblood",3,150); break; case 2: AddOneliner("koraxgame",3,120); break; case 3: AddOneliner("koraxworship",3,80); break; case 4: AddOneliner("koraxmasters",3,90); break; } } else if ( e.Name.Left(16) ~== "swwmremoteliner." ) { if ( consoleplayer == e.Args[0] ) return; if ( !swwm_othervoice ) return; if ( swwm_mutevoice >= e.Args[1] ) return; players[e.Args[0]].mo.A_StartSound(e.Name.Mid(16),CHAN_DEMOVOICE,attenuation:.5); } else if ( e.Name.Left(19) ~== "swwmremotelinertxt." ) { if ( consoleplayer == e.Args[0] ) return; if ( !swwm_othervoice ) return; if ( swwm_mutevoice >= e.Args[1] ) return; double dist = players[consoleplayer].Camera.Distance3D(players[e.Args[0]].mo); if ( dist < 2000 ) Console.Printf("\cx%s\cx: %s\c-",players[e.Args[0]].GetUserName(),StringTable.Localize(e.Name.Mid(19))); } else if ( e.Name.Left(8) ~== "swwmcbt." ) { // from wikipedia, the free encyclopedia if ( !playeringame[e.Args[0]] || !players[e.Args[0]].mo ) return; let cbt = Wallbuster(players[e.Args[0]].mo.FindInventory("Wallbuster")); if ( !cbt ) return; cbt.reloadqueue.Clear(); if ( e.Name.Mid(8) ~== "EMPTY" ) cbt.clearout = true; else { cbt.clearout = false; Array qs; qs.Clear(); String rite = e.Name.Mid(8); rite.Split(qs,",",TOK_SKIPEMPTY); for ( int i=0; i 3) ) continue; cbt.reloadqueue.Push(cbttypes[qi]); } } cbt.waitreload = false; } else if ( e.Name ~== "swwmcleartransaction" ) { if ( e.Args[1] != consoleplayer ) return; for ( int i=0; i)(AllActorClasses[i]); if ( !w || (w == 'SWWMWeapon') ) continue; let def = GetDefaultByType(w); if ( def.bCHEATNOTWEAPON ) continue; let ow = players[e.Args[0]].mo.FindInventory(w); if ( ow && (ow.Amount >= ow.MaxAmount) ) continue; if ( ow ) ow.Amount = ow.MaxAmount; else players[e.Args[0]].mo.GiveInventory(w,def.MaxAmount); } } else if ( e.Name ~== "swwmhealcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyRemember to stay fit.\c-"); S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI); S_StartSound("misc/health_pkup",CHAN_VOICE,CHANF_UI); } players[e.Args[0]].health = players[e.Args[0]].mo.health = 1000; } else if ( e.Name ~== "swwmynykroncheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyYou're still crazy.\c-"); S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI); S_StartSound("misc/w_pkup",CHAN_VOICE,CHANF_UI); } if ( players[e.Args[0]].mo.FindInventory("Ynykron") ) players[e.Args[0]].mo.GiveInventory("YnykronAmmo",1); else players[e.Args[0]].mo.GiveInventory("Ynykron",1); } else if ( e.Name ~== "swwmgravcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyGot something floatier.\c-"); S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI); S_StartSound("misc/p_pkup",CHAN_VOICE,CHANF_UI); } let g = GravityPower(players[e.Args[0]].mo.FindInventory("GravityPower")); if ( g ) g.EffectTics += g.default.EffectTics; else players[e.Args[0]].mo.GiveInventory("GravityPower",1); } else if ( e.Name ~== "swwminvischeat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyProbably because you're invisible.\c-"); S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI); S_StartSound("misc/p_pkup",CHAN_VOICE,CHANF_UI); } let g = GhostPower(players[e.Args[0]].mo.FindInventory("GhostPower")); if ( g ) g.EffectTics += g.default.EffectTics; else players[e.Args[0]].mo.GiveInventory("GhostPower",1); } else if ( e.Name ~== "swwmbarriercheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cySafe from those pesky elements.\c-"); S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI); S_StartSound("misc/p_pkup",CHAN_VOICE,CHANF_UI); } let b = BarrierPower(players[e.Args[0]].mo.FindInventory("BarrierPower")); if ( b ) b.EffectTics += b.default.EffectTics; else players[e.Args[0]].mo.GiveInventory("BarrierPower",1); } else if ( e.Name ~== "swwmammocheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyDon't squander it.\c-"); S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI); S_StartSound("misc/ammo_pkup",CHAN_VOICE,CHANF_UI); } players[e.Args[0]].mo.GiveInventory("HammerspaceEmbiggener",8,true); for ( Inventory i=players[e.Args[0]].mo.inv; i; i=i.inv ) { if ( !(i is 'Ammo') ) continue; i.Amount = i.MaxAmount; } } else if ( e.Name ~== "swwmbloodcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyEdgy...\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmexplocheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyThat cheat's not needed anymore.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmallcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyStill as wrappy as it's always been.\c-"); S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI); S_StartSound("fabricator/use",CHAN_VOICE,CHANF_UI); } players[e.Args[0]].mo.CheatGive("all",0); players[e.Args[0]].health = players[e.Args[0]].mo.health = 1000; } else if ( e.Name ~== "swwmflagcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyThere are no flags here.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmballcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cy\"Balls on your head\"? What was I even thinking...\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmsmartcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cySkittles are better anyway.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmnutcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyI'm way past that, it was bad for my health.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmweeniecheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyAlways has been.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmpunishcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyThis is a bulli free zone.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmball2cheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cy\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmfartcheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyI'd rather not reimplement that one.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmsupercheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyNo, you're the Demolitionist.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmstonecheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyThe pinnacle of... wait, I misread that.\c-"); S_StartSound("misc/nocheat",CHAN_ITEM,CHANF_UI); } } else if ( e.Name ~== "swwmfroggycheat" ) { 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); } else if ( e.Name ~== "swwmamnesiacheat" ) { if ( consoleplayer == e.Args[0] ) { Console.Printf("\cyAmnesiacs administered.\c-"); S_StartSound("misc/buyinv",CHAN_ITEM,CHANF_UI); S_StartSound("bestsound",CHAN_VOICE,CHANF_UI); } let ti = ThinkerIterator.Create("Actor"); Actor a; while ( a = Actor(ti.Next()) ) { if ( !a.bIsMonster || a.player ) continue; a.A_ClearTarget(); } } } // stuff for hud override void RenderUnderlay( RenderEvent e ) { // armor/health flashes int camplayer = players[consoleplayer].Camera.PlayerNumber(); if ( camplayer != -1 ) { if ( gametic < hflash[camplayer] ) { double fstr = (hflash[camplayer]-(gametic+e.FracTic))/5.; Screen.Dim(Color(64,128,255),.1875*fstr,0,0,Screen.GetWidth(),Screen.GetHeight()); } if ( gametic < aflash[camplayer] ) { double fstr = (aflash[camplayer]-(gametic+e.FracTic))/5.; Screen.Dim(Color(96,255,64),.1875*fstr,0,0,Screen.GetWidth(),Screen.GetHeight()); } } // weapon underlays if ( players[consoleplayer].ReadyWeapon is 'SWWMWeapon' ) SWWMWeapon(players[consoleplayer].ReadyWeapon).RenderUnderlay(e); if ( !statusbar || !(statusbar is 'SWWMStatusBar') ) return; SWWMStatusBar(statusbar).viewpos = e.viewpos; SWWMStatusBar(statusbar).viewrot = (e.viewangle,e.viewpitch,e.viewroll); if ( slotstrictwarn && (gametic < slotstrictwarn) ) { String str = StringTable.Localize("$SWWM_SETSLOTSTRICT"); double t = (slotstrictwarn-(gametic+e.FracTic))/20.; double alph = clamp(t,0.,1.); BrokenLines l = newsmallfont.BreakLines(str,300); double yy = (200-l.Count()*newsmallfont.GetHeight())/2; for ( int i=0; i 0) && (gametic < lastcummtic+150) ) { double calph = clamp(((lastcummtic+150)-gametic)/50.,0.,1.); string dnum = String.Format("%d",cummdamage); Screen.DrawText(dmgfnt,Font.CR_RED,vpos.x+300-dmgfnt.StringWidth(dnum),vpos.y-(dmgfnt.GetHeight()+2),dnum,DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha*calph); } Screen.DrawText(barfnt,Font.CR_WHITE,vpos.x,vpos.y-(barfnt.GetHeight()+2),StringTable.Localize(swwm_funtags?(bosstag.."_FUN"):bosstag),DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha); } 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); } // various shaders override void RenderOverlay( RenderEvent e ) { // cheat input if ( (kcode > 4) || ((klinger > gametic) && (klingerstr != "")) ) { double hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/266.)),1.); Vector2 ss = (Screen.GetWidth(),Screen.GetHeight())/hs; String chstr = (kcode>4)?kstr.Mid(4):klingerstr.Mid(4); double alph = clamp((klinger-(gametic+e.fractic))/20.,0.,1.); double shine = clamp((klinger-(gametic+e.fractic+40))/20.,0.,1.); int col = (kcode>4)?0:(kfail)?2:1; int tlen = chstr.CodePointCount(); let fnt = newsmallfont; int width = fnt.StringWidth(chstr)+(tlen-1); int xx = int((ss.x-width)/2.); int yy = int((ss.y-newsmallfont.GetHeight())/2.); rss = (kcode>4)?gametic:klinger; for ( int i=0, pos=0; i0)?demo.lastdamage:Random[Flicker](60,80); int lastdmgtic = (demo.Health>0)?demo.lastdamagetic:(gametic+Random[Flicker](30,20)); double noiz = min(lastdmg*.09*max(0,(lastdmgtic-(gametic+e.Fractic))/35.),.5); Shader.SetEnabled(p,"Glitch",noiz>0); Shader.SetEnabled(p,"Grain",noiz>0); if ( noiz > 0 ) { Shader.SetUniform1f(p,"Glitch","Timer",(gametic+e.FracTic)/GameTicRate); Shader.SetUniform1f(p,"Grain","Timer",(gametic+e.FracTic)/GameTicRate); Shader.SetUniform1f(p,"Grain","ni",noiz); noiz = min(lastdmg*.08*max(0,(lastdmgtic-(gametic+e.Fractic))/35.),.8); Shader.SetUniform1f(p,"Glitch","str1",noiz); noiz = min(lastdmg*.03*max(0,(lastdmgtic-(gametic+e.Fractic))/35.),3.5); Shader.SetUniform1f(p,"Glitch","str2",noiz); } if ( !demo.InStateSequence(demo.CurState,demo.FindState("Dash")) ) { Shader.SetEnabled(p,"ZoomBlur",false); return; } Shader.SetEnabled(p,"ZoomBlur",true); Vector3 vel = demo.vel+demo.dashdir*demo.dashboost; double baumpu = max(0.,(demo.bumptic-(gametic+e.Fractic))/35.); vel += demo.dashdir*baumpu; double spd = vel.length(); Vector3 worlddir = vel/spd; Shader.SetUniform1f(p,"ZoomBlur","Fade",clamp((spd-20.)/60.,0.,1.)); double str = min(spd/40.,15.); Vector3 x, y, z; [x, y, z] = swwm_CoordUtil.GetAxes(e.ViewPitch,e.ViewAngle,e.ViewRoll); Vector3 reldir = (worlddir dot y, worlddir dot z, worlddir dot x); Vector2 centerspot = (.5+reldir.x*.5,.5+reldir.y*.5); if ( reldir.z < 0 ) { centerspot.x = 1.-centerspot.x; centerspot.y = 1.-centerspot.y; str *= -1; } Shader.SetUniform1f(p,"ZoomBlur","Str",str); Shader.SetUniform2f(p,"ZoomBlur","CenterSpot",centerspot); } else { Shader.SetEnabled(p,"WaterWarp",false); Shader.SetEnabled(p,"LavaWarp",false); Shader.SetEnabled(p,"SlimeWarp",false); Shader.SetEnabled(p,"Glitch",false); Shader.SetEnabled(p,"Grain",false); Shader.SetEnabled(p,"ZoomBlur",false); } } static void DoFlash( Actor camera, Color c, int duration ) { // don't flash when paused if ( menuactive && (menuactive != Menu.OnNoPause) ) return; QueuedFlash qf = new("QueuedFlash"); qf.duration = duration; qf.c = c; qf.tic = gametic; qf.cam = camera; let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd ) return; // not supposed to happen hnd.flashes.push(qf); } // can't use this until I actually figure out how to make those walls damageable /*override void WorldLineDamaged( WorldEvent e ) { // allow boss brain to take (reduced) damage from the facewall being shot if ( level.mapname ~== "MAP30" ) { if ( !SWWMUtility.IsIOSWall(e.DamageLine) ) return; if ( bossbrainactor ) bossbrainactor.DamageMobj(e.Inflictor,e.DamageSource,e.Damage/3,e.DamageType,e.DamageFlags,e.DamageAngle); e.NewDamage = 0; } }*/ }