// all the player* virtuals extend Class SWWMHandler { 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 foreach ( pc:PlayerClasses ) { if ( !(p.mo is pc.Type) ) continue; // perform a hotswap, code adapted from my .flow player morph in spooktober let n = PlayerPawn(Actor.Spawn('Demolitionist',p.mo.pos)); n.player = p; n.angle = p.mo.angle; n.pitch = p.mo.pitch; p.camera = n; p.mo.Destroy(); p.mo = n; n.GiveDefaultInventory(); let e = Weapon(n.FindInventory('ExplodiumGun')); if ( e ) { p.ReadyWeapon = null; p.PendingWeapon = e; n.BringUpWeapon(); } // warn if strict KEYCONF is enabled if ( setslotstrict && (p == players[consoleplayer]) ) slotstrictwarn = gametic+300; break; } } // create some static thinkers for this player if needed SWWMCredits c = SWWMCredits.Find(p); if ( !c ) { c = new('SWWMCredits'); c.ChangeStatNum(Thinker.STAT_STATIC); c.myplayer = p; } SWWMLoreLibrary l = SWWMLoreLibrary.Find(p); if ( !l ) { l = new('SWWMLoreLibrary'); l.ChangeStatNum(Thinker.STAT_STATIC); l.myplayer = p; } // pre-add some entries to start with l.DirectAdd("Demolitionist"); l.DirectAdd("KnowledgeBase"); l.DirectAdd("Saya"); l.DirectAdd("UAC"); l.DirectAdd("DemonInvasion"); if ( SWWMUtility.IsEviternity() || SWWMUtility.IsEviternityTwo() ) { l.DirectAdd("Gods"); l.DirectAdd("SUSAN"); } if ( gameinfo.gametype&GAME_Raven ) { l.DirectAdd("Parthoris"); l.DirectAdd("SerpentRiders"); l.DirectAdd("Sidhe"); } if ( gameinfo.gametype&GAME_Hexen ) l.DirectAdd("Cronos"); // starting weapons (if owned) if ( p.mo.FindInventory('DeepImpact') ) l.DirectAdd("DeepImpact"); if ( p.mo.FindInventory('ExplodiumGun') ) l.DirectAdd("ExplodiumGun"); SWWMStats s = SWWMStats.Find(p); if ( !s ) { s = new('SWWMStats'); s.ChangeStatNum(Thinker.STAT_STATIC); s.myplayer = p; s.lastspawn = level.totaltime; s.favweapon = -1; for ( Inventory i=p.mo.Inv; i; i=i.inv ) { if ( !(i is 'Weapon') ) continue; // skip dual weapons if their sister weapon amount isn't 2 String cn = i.GetClassName(); if ( cn.Left(4) ~== "Dual" ) { let ss = Weapon(i).SisterWeapon; if ( !ss || (ss.Amount == 1) ) continue; } s.GotWeapon(Weapon(i).GetClass()); } } else if ( level.info.flags2&LEVEL2_RESETINVENTORY && !e.IsReturn ) s.CleanGotWeapons(); // clean up the "got weapons" so their obtain lines are played again s.PreloadLevelStats(); // reset some vars multilevel[e.playernumber] = 0; spreecount[e.playernumber] = 0; tookdamage[e.playernumber] = false; lastkill[e.playernumber] = int.min; // reset score (optional) if inventory should be cleared if ( swwm_resetscore && level.info.flags2&LEVEL2_RESETINVENTORY && !e.IsReturn ) c.credits = 0; // re-add any missing collectibles after a death exit (yes, this happens) foreach ( oc:s.ownedcollectibles ) { if ( p.mo.FindInventory(oc) ) continue; let c = SWWMCollectible(Actor.Spawn(oc,p.mo.pos)); c.propagated = true; if ( !c.CallTryPickup(p.mo) ) c.Destroy(); } // cap health to 200 if ( p.Health > 200 ) p.Health = p.mo.Health = 200; } 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; } }