// Handler responsible for item replacements and whatever else // most of the code is split up to make it easier to navigate Class SWWMHandler : EventHandler { transient int lastlock; transient int lastpickuptic[MAXPLAYERS]; SWWMScoreObj scorenums; SWWMDamNum damnums; SWWMInterest intpoints; Array damtypes, damcolors; transient CVar usedamcolors; transient int slotstrictwarn; transient ui String sswstr; transient ui BrokenLines sswl; // stuff to reduce worldthingspawned overhead int bossmap; int iwantdie; int indoomvacation; int inultdoom2; Array funtagsv, mergemonstersv; // for checkreplacement bool hasdrlamonsters, haslegionofbones; int iskdizd; Array bludtypes; // mod inter-compat stuff bool ccloaded; // session globals SWWMGlobals gdat; // profiling data bool profiling; int bprofiletics, profiletics; // how many tics to aggregate data for double prof_ms[8], prof_avg[8]; int prof_calls[8]; double curms; enum EProfileTimer { PT_WORLDTICK, PT_WORLDTHINGSPAWNED, PT_WORLDTHINGDESTROYED, PT_WORLDTHINGDIED, PT_WORLDTHINGDAMAGED, PT_WORLDTHINGREVIVED, PT_CHECKREPLACEMENT, PT_CHECKREPLACEE } private void ProfileTick() { curms = MSTimeF(); } private void ProfileTock( int idx ) { double diff = (MSTimeF()-curms); prof_ms[idx] += diff; prof_avg[idx] = (prof_calls[idx]>0)?(prof_avg[idx]+diff)/2.:diff; prof_calls[idx]++; } override void OnRegister() { // oneliner RNG must be relative to consoleplayer SetRandomSeed[DemoLines](Random[DemoLines]()+consoleplayer+int(MSTimeF())); // "uninitialize" some vars iwantdie = -1; bossmap = -1; indoomvacation = -1; inultdoom2 = -1; // class-checking ones can be initialized here easily for ( int i=0; i list; // fucking Windows dat.Replace("\r",""); list.Clear(); dat.Split(list,"\n"); for ( int i=0; i list; // fucking Windows dat.Replace("\r",""); list.Clear(); dat.Split(list,"\n"); for ( int i=0; i1)?"s":""); } override void WorldTick() { if ( profiling ) ProfileTick(); LangRefresh(); QueueMaintenance(); if ( !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")); } } for ( int i=0; i 0) ) SWWMQuickCombatTracker.Update(self,players[i],t); // keep healthbars updated for all friends of this player for ( int j=0; j 0 ) return; profiling = false; static const String prof_name[] = { "WorldTick ", "WorldThingSpawned ", "WorldThingDestroyed", "WorldThingDied ", "WorldThingDamaged ", "WorldThingRevived ", "CheckReplacement ", "CheckReplacee " }; Console.Printf("Done!"); String str = String.Format( "SWWMHandler profiling info for %d tic%s:\n" " event name | calls | total ms | avg ms\n" "---------------------|--------|-------------|-------------\n", bprofiletics,(bprofiletics>1)?"s":""); for ( int i=0; i<8; i++ ) str.AppendFormat(" %s | %6d | %11.6f | %11.6f\n",prof_name[i],prof_calls[i],prof_ms[i],prof_avg[i]); Console.Printf(str); } override void PostUiTick() { OnelinerUITick(); FlashUITick(); VanillaBossUITick(); MapstartUITick(); } override void WorldLinePreActivated( WorldEvent e ) { // oneliner on locked doors if ( !e.Thing ) return; int locknum = SWWMUtility.GetLineLock(e.ActivatedLine); if ( (locknum < 1) || (locknum > 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; if ( (e.Thing.player == players[consoleplayer]) && swwm_beepboop ) SWWMHandler.AddOneliner("buttonpush",2,0); let w = SWWMWeapon(e.Thing.player.ReadyWeapon); if ( (!w || !w.wallponch) && (!(e.Thing is 'Demolitionist') || !Demolitionist(e.Thing).hitactivate) ) return; let s = SWWMStats.Find(e.Thing.player); if ( s ) s.wponch++; SWWMUtility.AchievementProgressInc("slemg",1,e.Thing.player); } // stuff for hud override void RenderUnderlay( RenderEvent e ) { // armor/health flashes FlashRender(e); if ( slotstrictwarn && (gametic < slotstrictwarn) ) { String str = StringTable.Localize("$SWWM_SETSLOTSTRICT"); if ( sswstr != str ) { sswstr = str; if ( sswl ) sswl.Destroy(); } double t = (slotstrictwarn-(gametic+e.FracTic))/20.; double alph = clamp(t,0.,1.); if ( !sswl ) sswl = newsmallfont.BreakLines(sswstr,300); double yy = (200-sswl.Count()*newsmallfont.GetHeight())/2; for ( int i=0; i