// hud-related storage objects // (used to be thinkers, but this might be lighter on performance) // floating scores Class SWWMScoreObj play { Array xtcolor; Array xscore; Array xstr; int tcolor; int score; Vector3 pos; int lifespan, initialspan; int starttic, seed, seed2; SWWMScoreObj next; static SWWMScoreObj Spawn( int score, Vector3 pos, int tcolor = -1 ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd ) return null; return SpawnFromHandler(hnd,score,pos,tcolor); } static SWWMScoreObj SpawnFromHandler( SWWMHandler hnd, int score, Vector3 pos, int tcolor = -1 ) { let o = new("SWWMScoreObj"); o.score = score; o.pos = pos; o.lifespan = o.initialspan = 60; if ( tcolor != -1 ) o.tcolor = tcolor; else o.tcolor = Font.CR_GOLD; o.starttic = level.maptime; o.seed = Random[ScoreBits](); o.seed2 = Random[ScoreBits](); o.next = hnd.scorenums; hnd.scorenums = o; return o; } void AppendXString( String xstr, int xscore = 0, int xtcolor = int.min ) { self.xscore.Push(xscore); self.xstr.Push(xstr); self.xtcolor.Push((xtcolor==int.min)?Font.CR_FIRE:xtcolor); } bool Tick() { lifespan--; return (lifespan <= 0); } } // damage/health/armor numbers Class SWWMDamNum play { int tcolor; int damage; Vector3 pos; int lifespan, initialspan; int starttic, seed, seed2; SWWMDamNum next; static SWWMDamNum Spawn( int damage, Vector3 pos, Name type = '' ) { let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( !hnd ) return null; return SpawnFromHandler(hnd,damage,pos,type); } static SWWMDamNum SpawnFromHandler( SWWMHandler hnd, int damage, Vector3 pos, Name type = '' ) { let o = new("SWWMDamNum"); o.damage = damage; o.pos = pos; o.tcolor = Font.FindFontColor("MiniRed"); if ( !hnd.usedamcolors ) hnd.usedamcolors = CVar.FindCVar('swwm_damnums_color'); if ( hnd.usedamcolors.GetBool() ) for ( int i=0; i k = thekey.species; let def = GetDefaultByType(k); i.marker.picnum = def.SpawnState.GetSpriteTexture(0); } else i.marker.picnum = thekey.SpawnState.GetSpriteTexture(0); i.marker.target = thekey; i.marker.scale = thekey.scale; i.marker.bDORMANT = !level.allmap; } else if ( theline ) { i.type = INT_Exit; i.exittype = theexit; i.marker = Actor.Spawn("SWWMInterestMarker",pos); i.marker.SetState(i.marker.SpawnState+theexit); i.marker.bDORMANT = !level.allmap; } else { i.Destroy(); return null; } i.pos = thekey?thekey.Vec3Offset(0,0,thekey.height/2):pos; i.next = hnd.intpoints; hnd.intpoints = i; return i; } bool Tick() { // update if ( (type == INT_Key) && (!trackedkey || trackedkey.Owner) ) { marker.Destroy(); return true; } if ( trackedkey ) { pos = trackedkey.Vec3Offset(0,0,trackedkey.height/2); marker.SetOrigin(pos,true); } return false; } } Class SWWMItemSense play { Actor item; String tag; int updated; bool scoreitem, vipitem; Demolitionist parent; SWWMItemSense next; Vector3 pos; static SWWMItemSense Spawn( Demolitionist parent, Actor item ) { if ( !parent || !item ) return null; // only refresh the updated time if existing for ( SWWMItemSense s=parent.itemsense; s; s=s.next ) { if ( s.item != item ) continue; s.updated = level.maptime+35; s.pos = item.Vec3Offset(0,0,item.height); return s; } let i = new("SWWMItemSense"); i.item = item; if ( item is 'SWWMRespawnTimer' ) { i.scoreitem = SWWMUtility.IsScoreItem(item.tracer); i.vipitem = SWWMUtility.IsVipItem(item.tracer); } else { i.scoreitem = SWWMUtility.IsScoreItem(item); i.vipitem = SWWMUtility.IsVipItem(item); } i.parent = parent; i.updated = level.maptime+35; i.UpdateTag(); i.pos = item.Vec3Offset(0,0,item.height); i.next = parent.itemsense; parent.itemsense = i; return i; } void UpdateTag() { let i = item; if ( i is 'SWWMRespawnTimer' ) i = i.tracer; if ( !i ) return; // our ammo types use the pickup message, as it's amount-aware if ( (i is 'SWWMAmmo') || (i is 'MagAmmo') ) tag = Inventory(i).PickupMessage(); else tag = i.GetTag(); } bool Tick() { // expire if ( !parent || (level.maptime > updated+70) ) return true; return false; } } // ultralight trackers for certain things Class SWWMSimpleTracker play { Actor target; double radius; double angle; Vector3 pos; bool isplayer; Color playercol; bool ismonster; bool friendly; bool countkill; bool shootable; bool isitem; bool countitem; bool vipitem; bool expired; bool ismissile; bool isbeam, isybeam; int lastupdate; ui double smoothalpha; // smoothened alpha, for ui SWWMSimpleTracker next; void Update() { if ( !target ) return; isbeam = SWWMUtility.IsBeamProj(target); isybeam = isbeam&&SWWMUtility.IsYBeam(target); radius = isybeam?(target.scale.y*cos(target.pitch+90)):isbeam?(target.speed*cos(target.pitch)):target.radius; angle = target.angle; pos = target.pos; isplayer = target.player; if ( isplayer ) playercol = target.player.GetColor(); ismonster = target.bISMONSTER; friendly = target.IsFriend(players[consoleplayer].mo); countkill = target.bCOUNTKILL; shootable = target.default.bSHOOTABLE; ismissile = isbeam||target.default.bMISSILE; isitem = (target is 'Inventory'); countitem = SWWMUtility.IsScoreItem(target); vipitem = SWWMUtility.IsVipItem(target); lastupdate = level.maptime; if ( isitem ) { if ( !target.bSPECIAL || Inventory(target).Owner ) expired = true; else { expired = false; lastupdate += 35; if ( countitem ) lastupdate += 35; if ( vipitem ) lastupdate += 70; } } else if ( vipitem ) { if ( (target is 'Chancebox') && (target.CurState != target.SpawnState) ) expired = true; else { expired = false; lastupdate += 70; } } else if ( friendly ) { expired = target.bKILLED; if ( expired ) lastupdate += 35; else lastupdate += 140; } else if ( ismonster ) { expired = target.bKILLED||target.bUnmorphed; if ( !expired ) { lastupdate += 35; if ( target.target == players[consoleplayer].mo ) lastupdate += 70; } } else if ( ismissile && !isbeam ) expired = !target.bMISSILE; else if ( target.default.bSHOOTABLE ) expired = (target.Health<=0); } static SWWMSimpleTracker Track( SWWMHandler hnd, Actor target ) { SWWMSimpleTracker t; for ( t=hnd.strackers; t; t=t.next ) { if ( t.target != target ) continue; t.Update(); return t; } t = new("SWWMSimpleTracker"); t.target = target; t.Update(); t.next = hnd.strackers; hnd.strackers = t; return t; } }