class ScrnHUD extends SRHUDKillingFloor; #exec OBJ LOAD FILE=ScrnTex.utx #exec OBJ LOAD FILE=ScrnAch_T.utx //var byte colR, colG, colB; var localized string strCowboyMode; var() config int MinMagCapacity; //don't show low ammo warning, if weapon magazine smaller than this var() config float LowAmmoPercent; // set inside CalculateAmmo() var transient bool bLowAmmo; var transient float WeaponChargePct; //0..1 var transient int WeaponMaxCharge; var transient float MaxAmmoSecondary; // including perk bonus var transient int CurMagAmmo; var() texture texCowboy; var() config float CowboyTileWidth; var() float CowboyTileY; var() SpriteWidget BlamedIcon; var float BlamedIconSize; var() SpriteWidget SingleNadeIcon; // configurable variables from ScrnBuyMenuSaleList var globalconfig color TraderGroupColor, TraderActiveGroupColor, TraderSelectedGroupColor; var globalconfig Color TraderPriceButtonColor, TraderPriceButtonDisabledColor, TraderPriceButtonSelectedColor; var protected class ScrnScoreBoardClass; // modder friendly interface // vars below are set inside LinkActors() var protected transient class ScrnPerk; var private transient class PrevPerk; var protected transient ScrnHumanPawn ScrnPawnOwner; // ScrN Pawn we are playing or spectating var protected transient KFWeapon OwnerWeapon; var protected transient class OwnerWeaponClass; var protected transient ScrnGameReplicationInfo ScrnGRI; var protected transient ScrnCustomPRI ScrnPRI; var protected transient bool bSpecialPortrait; // if true, then player's avatar is drawn instead of character var protected transient bool bSpectating; // are we spectating? var protected transient bool bSpectatingScrn; // are we spectating ScrnHumanPawn var protected transient bool bSpectatingZED; // are we spectating KFMonster var protected transient bool bCoolHudActive; // is new hud active atm? var HudOverlay PerkOverlay; var Material CriticalOverlay; var transient float CriticalOverlayTimer; var config byte SpecHeaderFont; var localized string strFollowing; var localized string strTrader; var config bool bCoolHud; var config float CoolHudScale; var config bool bCoolHudLeftAlign; var config float CoolHudAmmoOffsetX, CoolHudAmmoOffsetY, CoolHudAmmoScale; var bool bCoolHudTeamColor; var color CoolHudColor, CoolHudAmmoColor; var config byte PlayerInfoVersionNumber; var config float PlayerInfoScale; var Material CoolBarBase,CoolBarOverlay; var int CoolBarSize, CoolHealthBarTop, CoolHealthBarHeight; var color HealthBarColor, HealingBarColor, FullHealthColor, OverchargeHealthColor, LowHealthColor, ArmorBarColor, BigArmorColor; var float CoolPerkToBarSize, CoolStarToBarSize, CoolStarAngleRad, CoolPerkOffsetY, CoolPerkLevelOffsetY; var float CoolIconToBarSize; var transient bool bHealthFadeOut; var transient float HealthFading; var protected transient int OldHealth, OldArmor; var config float CoolHealthFadeOutTime; var localized string strBonusLevel; var() NumericWidget CoolPerkLevelDigits; var() SpriteWidget CoolCashIcon; var() NumericWidget CoolCashDigits; var transient float PulseAlpha; var float PulseRate; var transient bool bDrawingBonusLevel, bXPBonusFadingOut, bXPBonusFadingIn; var transient float CoolPerkAlpha; var transient float XPBonusNextPlaseTime, XPBonusFadeTime; var float XPLevelShowTime, BonusLevelShowTime, XPBonusFadeRate; var protected transient float MsgTopY; // top Y coordinate up upper console message displayed on the HUD struct SHitInfo { var string Text; var float LastHit; }; struct DamageInfo { var int Damage; var float HitTime; var Vector HitLocation; var byte DamTypeNum; var float RandX, RandY; var color FontColor; }; const DAMAGEPOPUP_COUNT = 32; var DamageInfo DamagePopups[32]; var int NextDamagePopupIndex; var() config bool bShowDamages; var() config byte DamagePopupFont; var() config float DamagePopupFadeOutTime; var() config bool bShowSpeed; var() config float SpeedometerX, SpeedometerY; var() config byte SpeedometerFont; var bool bHidePlayerInfo; var config bool bOldStyleIcons; var class BlamedMonsterClass; var float BlameCountdown; var float BlameDrawDistance; // max distance to draw a turn on blamed pawn's head var config bool bDrawSpecDeaths; var Color WhiteAlphaColor; // white color with applied KFHUDAlpha. It is safe to use default.WhiteAlphaColor as well var array PerkColors; var color TeamColors[2]; // moved from TSCHUD var color TextColors[2]; var localized string strPendingItems; var material ChatIcon; var bool bZedHealthShow; function PostBeginPlay() { super.PostBeginPlay(); // prevent using spedometer as crosshair if ( SpeedometerX > 0.4 && SpeedometerX < 0.6 && SpeedometerY > 0.4 && SpeedometerY < 0.6 ) { SpeedometerX = 0.985; SpeedometerY = 0.80; PlayerOwner.ClientMessage("HUD Cheat Prevention: Speedometer position set to default"); } class'ScrnBalanceSrv.ScrnVeterancyTypes'.default.bOldStyleIcons = bOldStyleIcons; if ( MyColorMod==None ) { MyColorMod = ColorModifier(Level.ObjectPool.AllocateObject(class'ColorModifier')); MyColorMod.AlphaBlend = True; MyColorMod.Color.R = 255; MyColorMod.Color.B = 255; MyColorMod.Color.G = 255; } SpecHeaderFont = clamp(SpecHeaderFont, 0, 1); PlayerInfoVersion(PlayerInfoVersionNumber); // force update } function Destroyed() { if ( PerkOverlay != none ) PerkOverlay.Destroy(); super.Destroyed(); } // Draw Health Bars for damage opened doors. function DrawDoorHealthBars(Canvas C) { local KFDoorMover DamageDoor; local vector CameraLocation, CamDir, TargetLocation, HBScreenPos; local rotator CameraRotation; local name DoorTag; local int i; local float Distance; if( PawnOwner==None ) return; if ( (Level.TimeSeconds>LastDoorBarHealthUpdate) || (Welder(PawnOwner.Weapon)!=none && PlayerOwner.bFire==1) ) { Distance = 300.00; //while holding welder door health bars are visible from longer distance if ( ScrnPerk != none && Welder(PawnOwner.Weapon) != none) { Distance *= ScrnPerk.static.GetDoorHealthVisibilityScaling(KFPRI, PawnOwner); } DoorCache.Length = 0; foreach CollidingActors(class'KFDoorMover', DamageDoor, Distance, PlayerOwner.CalcViewLocation) { if ( DamageDoor.WeldStrength<=0 ) continue; DoorCache[DoorCache.Length] = DamageDoor; C.GetCameraLocation(CameraLocation, CameraRotation); TargetLocation = DamageDoor.WeldIconLocation; TargetLocation.Z = CameraLocation.Z; CamDir = vector(CameraRotation); if ( Normal(TargetLocation - CameraLocation) dot Normal(CamDir) >= 0.1 && DamageDoor.Tag != DoorTag && FastTrace(DamageDoor.WeldIconLocation - ((DoorCache[i].WeldIconLocation - CameraLocation) * 0.25), CameraLocation) ) { HBScreenPos = C.WorldToScreen(TargetLocation); DrawDoorBar(C, HBScreenPos.X, HBScreenPos.Y, DamageDoor.WeldStrength / DamageDoor.MaxWeld, 255); DoorTag = DamageDoor.Tag; } } LastDoorBarHealthUpdate = Level.TimeSeconds+0.2; } else { for ( i = 0; i < DoorCache.Length; i++ ) { if ( DoorCache[i].WeldStrength<=0 ) continue; C.GetCameraLocation(CameraLocation, CameraRotation); TargetLocation = DoorCache[i].WeldIconLocation; TargetLocation.Z = CameraLocation.Z; CamDir = vector(CameraRotation); if ( Normal(TargetLocation - CameraLocation) dot Normal(CamDir) >= 0.1 && DoorCache[i].Tag != DoorTag && FastTrace(DoorCache[i].WeldIconLocation - ((DoorCache[i].WeldIconLocation - CameraLocation) * 0.25), CameraLocation) ) { HBScreenPos = C.WorldToScreen(TargetLocation); DrawDoorBar(C, HBScreenPos.X, HBScreenPos.Y, DoorCache[i].WeldStrength / DoorCache[i].MaxWeld, 255); DoorTag = DoorCache[i].Tag; } } } } simulated function DrawCowboyMode(Canvas C) { C.SetDrawColor(255, 64, 64, KFHUDAlpha); C.SetPos(0.5 * C.ClipX * (1.0 - CowboyTileWidth), C.ClipY * CowboyTileY); C.DrawTile(texCowboy, C.ClipX * CowboyTileWidth, 64 * (C.ClipX * CowboyTileWidth)/512.0, 0, 0, 512, 64); } simulated function string GetSpeedStr(Canvas C) { local int Speed; local string s; local vector Velocity2D; if ( PawnOwner == none ) return s; Velocity2D = PawnOwner.Velocity; Velocity2D.Z = 0; Speed = VSize(Velocity2D); s = string(Speed); if ( PlayerOwner.Pawn == PawnOwner ) { // GroundSpeed is replicated to owner pawn only Speed = PawnOwner.GroundSpeed; s $= "/" $ Speed; } if ( Speed > 240 ) { // speed bonus - in blue C.DrawColor.R = 0; C.DrawColor.G = 100; C.DrawColor.B = 255; } else if ( Speed > 200 ) { // melee speed - in green C.DrawColor.R = 0; C.DrawColor.G = 206; C.DrawColor.B = 0; } else { // red C.DrawColor.R = 255; C.DrawColor.G = 64; C.DrawColor.B = 64; } C.DrawColor.A = KFHUDAlpha; return s; } simulated function DrawCookingBar(Canvas C) { //local inventory inv; local ScrnFrag aFrag; local float MyBarPercentage; local float MyBarLength, MyBarHeight, PosX, PosY; local float colR, colG; if ( KFPawn(PawnOwner) == none ) return; aFrag = ScrnFrag(KFPawn(PawnOwner).SecondaryItem); if ( aFrag == none || !aFrag.bCooking) return; if ( ScrnPerk == none || !ScrnPerk.static.CanShowNadeCookingBar(KFPRI) ) return; MyBarPercentage = 1.0 - fclamp((aFrag.CookExplodeTimer - Level.TimeSeconds) / class'ScrnBalanceSrv.ScrnNade'.default.ExplodeTimer, 0, 1); MyBarLength = C.ClipX * 0.2; MyBarHeight = 12; PosX = (C.ClipX - MyBarLength) / 2; PosY = C.ClipY * 0.8; //bottom center //border C.SetPos(PosX, PosY); C.SetDrawColor(192, 192, 192, KFHUDAlpha); C.DrawTileStretched(WhiteMaterial, MyBarLength, MyBarHeight); //fill C.SetPos(PosX + 1.0, PosY + 1.0); // green -> yellow -> red if ( MyBarPercentage > 0.5 ) colR = 255; if ( MyBarPercentage < 0.75 ) colG = 255; C.SetDrawColor(colR, colG, 0, KFHUDAlpha); C.DrawTileStretched(WhiteMaterial, (MyBarLength - 2.0) * MyBarPercentage, MyBarHeight - 2.0); } simulated function DrawEndGameHUD(Canvas C, bool bVictory) { super.DrawEndGameHUD(C, bVictory); //display end-game achievements C.Reset(); DisplayLocalMessages(C); } final static function String FormatTime( int Seconds ) { local int Minutes, Hours; local String Time; if( Seconds > 3600 ) { Hours = Seconds / 3600; Seconds -= Hours * 3600; Time = Hours$":"; } Minutes = Seconds / 60; Seconds -= Minutes * 60; if( Minutes >= 10 ) Time = Time $ Minutes $ ":"; else Time = Time $ "0" $ Minutes $ ":"; if( Seconds >= 10 ) Time = Time $ Seconds; else Time = Time $ "0" $ Seconds; return Time; } simulated function DrawHudPassA (Canvas C) { DrawStoryHUDInfo(C); DrawDoorHealthBars(C); if ( ScrnPawnOwner != none && ScrnPawnOwner.bCowboyMode && !bShowScoreBoard && !bSpectating ) DrawCowboyMode(C); if ( bCoolHudActive ) { // draw new HUD DrawCoolHud(C); // some old HUD items if ( HealthFading > 5 ) { if ( bCoolHudLeftAlign ) { HealthDigits.OffsetX = 64*(CoolHudScale-2) - 4*CoolHudScale - 48; ArmorDigits.OffsetX = 128*(CoolHudScale-2) + 4*CoolHudScale + 32; HealthDigits.OffsetY = -72*CoolHudScale + 16; ArmorDigits.OffsetY = HealthDigits.OffsetY; } HealthIcon.Tints[0].A = HealthFading; HealthIcon.Tints[1].A = HealthFading; HealthDigits.Tints[0].A = HealthFading; HealthDigits.Tints[1].A = HealthFading; if ( !bCoolHudLeftAlign ) DrawSpriteWidget(C, HealthIcon); DrawNumericWidget(C, HealthDigits, DigitsSmall); if ( ArmorDigits.Value > 0 ) { ArmorIcon.Tints[0].A = HealthFading; ArmorIcon.Tints[1].A = HealthFading; ArmorDigits.Tints[0].A = HealthFading; ArmorDigits.Tints[1].A = HealthFading; if ( !bCoolHudLeftAlign ) DrawSpriteWidget(C, ArmorIcon); DrawNumericWidget(C, ArmorDigits, DigitsSmall); } HealthDigits.OffsetX = 0; ArmorDigits.OffsetX = 0; HealthDigits.OffsetY = 0; ArmorDigits.OffsetY = 0; } if ( bDisplayQuickSyringe ) DrawQuickSyringe(C); } else { // restore health alpha to default HealthIcon.Tints[0].A = KFHUDAlpha; HealthIcon.Tints[1].A = KFHUDAlpha; HealthDigits.Tints[0].A = KFHUDAlpha; HealthDigits.Tints[1].A = KFHUDAlpha; ArmorIcon.Tints[0].A = KFHUDAlpha; ArmorIcon.Tints[1].A = KFHUDAlpha; ArmorDigits.Tints[0].A = KFHUDAlpha; ArmorDigits.Tints[1].A = KFHUDAlpha; // classic hud DrawOldHudItems(C); } if ( bZedHealthShow ) DrawZedHealth(C); else if ( ScrnPerk != none ) ScrnPerk.Static.SpecialHUDInfo(KFPRI, C); if ( Level.TimeSeconds - LastVoiceGainTime < 0.333 ) { if ( !bUsingVOIP && PlayerOwner != None && PlayerOwner.ActiveRoom != None && PlayerOwner.ActiveRoom.GetTitle() == "Team" ) { bUsingVOIP = true; PlayerOwner.NotifySpeakingInTeamChannel(); } DisplayVoiceGain(C); } else bUsingVOIP = false; if ( bDisplayInventory || bInventoryFadingOut ) DrawInventory(C); if ( BlamedMonsterClass != none ) DrawBlameIcons(C); if ( bShowDamages ) DrawDamage(C); if ( bSpectatingScrn || bSpectatingZED ) DrawFirstPersonSpectatorHUD(C); else { if ( ScrnPawnOwner != none ) { DrawCookingBar(C); } if ( Level.NetMode == NM_Client && ScrnClientPerkRepLink(ClientRep) != none && ScrnClientPerkRepLink(ClientRep).PendingItems > 0 ) { C.Font = GetConsoleFont(C); C.SetPos(0, 0); C.SetDrawColor(160, 160, 160, 255); C.DrawText(strPendingItems @ ScrnClientPerkRepLink(ClientRep).PendingItems); } } } simulated function DrawHudPassC(Canvas C) { DrawFadeEffect(C); if ( bShowScoreBoard && ScoreBoard != None ) ScoreBoard.DrawScoreboard(C); // portrait if ( bShowPortrait && (Portrait != None) ) DrawPortraitSE(C); // finally this is not final :) -- PooSH if( bCrosshairShow && bShowKFDebugXHair ) DrawCrosshair(C); // Slow, for debugging only if( bDebugPlayerCollision && (class'ROEngine.ROLevelInfo'.static.RODebugMode() || Level.NetMode == NM_StandAlone) ) DrawPointSphere(); } simulated function DrawQuickSyringe(Canvas C) { local float t; local byte A; local Syringe S; t = Level.TimeSeconds - QuickSyringeStartTime; // time elapsed if ( t > QuickSyringeDisplayTime ) { bDisplayQuickSyringe = false; return; } S = Syringe(PawnOwner.FindInventoryType(class'Syringe')); if ( S == none ) { QuickSyringeDigits.Value = 0; } else QuickSyringeDigits.Value = S.ChargeBar() * 100; if ( QuickSyringeDigits.Value < 50 ) { QuickSyringeDigits.Tints[0].R = 128; QuickSyringeDigits.Tints[0].G = 128; QuickSyringeDigits.Tints[0].B = 128; } else if ( QuickSyringeDigits.Value < 100 ) { QuickSyringeDigits.Tints[0].R = 192; QuickSyringeDigits.Tints[0].G = 96; QuickSyringeDigits.Tints[0].B = 96; } else QuickSyringeDigits.Tints[0] = default.QuickSyringeDigits.Tints[0]; QuickSyringeDigits.Tints[1] = QuickSyringeDigits.Tints[0]; if ( bCoolHudActive && !bCoolHudLeftAlign ) { QuickSyringeIcon.PosX = WeightIcon.PosX; QuickSyringeDigits.PosX = WeightDigits.PosX; } else { QuickSyringeIcon.PosX = default.QuickSyringeIcon.PosX; QuickSyringeDigits.PosX = default.QuickSyringeDigits.PosX; } A = KFHUDAlpha; if ( t < QuickSyringeFadeInTime ) A = 255 * t / QuickSyringeFadeInTime; else { t = QuickSyringeDisplayTime - t; // time remaining if ( t < QuickSyringeFadeOutTime ) A = 255 * t / QuickSyringeFadeOutTime; } A = min(A, KFHUDAlpha); QuickSyringeBG.Tints[0].A = A; QuickSyringeBG.Tints[1].A = A; QuickSyringeIcon.Tints[0].A = A; QuickSyringeIcon.Tints[1].A = A; QuickSyringeDigits.Tints[0].A = A; QuickSyringeDigits.Tints[1].A = A; if ( !bLightHud && !bCoolHudActive ) DrawSpriteWidget(C, QuickSyringeBG); DrawSpriteWidget(C, QuickSyringeIcon); DrawNumericWidget(C, QuickSyringeDigits, DigitsSmall); } simulated function DrawOldHudItems(Canvas C) { local byte Counter, TempLevel; local float TempX, TempY, TempSize, BonusPerkX; local Material TempMaterial, TempStarMaterial; if ( bShowSpeed ) { C.Font = LoadSmallFontStatic(SpeedometerFont); C.SetPos(C.ClipX * SpeedometerX, C.ClipY * SpeedometerY); C.DrawText(GetSpeedStr(C) $ " ups"); } // HEALTH if ( !bLightHud && !bSpectatingZED ) DrawSpriteWidget(C, HealthBG); DrawSpriteWidget(C, HealthIcon); DrawNumericWidget(C, HealthDigits, DigitsSmall); if ( bSpectatingZED ) return; // ARMOR if ( !bLightHud ) DrawSpriteWidget(C, ArmorBG); if ( !bLightHud || ArmorDigits.Value > 0 ) { DrawSpriteWidget(C, ArmorIcon); DrawNumericWidget(C, ArmorDigits, DigitsSmall); } // WEIGHT if ( ScrnPawnOwner != none ) { C.SetPos(C.ClipX * WeightBG.PosX, C.ClipY * WeightBG.PosY); if ( !bLightHud ) C.DrawTile(WeightBG.WidgetTexture, WeightBG.WidgetTexture.MaterialUSize() * WeightBG.TextureScale * 1.5 * HudCanvasScale * ResScaleX * HudScale, WeightBG.WidgetTexture.MaterialVSize() * WeightBG.TextureScale * HudCanvasScale * ResScaleY * HudScale, 0, 0, WeightBG.WidgetTexture.MaterialUSize(), WeightBG.WidgetTexture.MaterialVSize()); DrawSpriteWidget(C, WeightIcon); C.Font = LoadSmallFontStatic(5); C.FontScaleX = C.ClipX / 1024.0; C.FontScaleY = C.FontScaleX; C.SetPos(C.ClipX * WeightDigits.PosX, C.ClipY * WeightDigits.PosY); C.DrawColor = WeightDigits.Tints[0]; if ( bSpectating ) C.DrawText(string(ScrnPawnOwner.SpecWeight)); else C.DrawText(int(ScrnPawnOwner.CurrentWeight)$"/"$int(ScrnPawnOwner.MaxCarryWeight)); C.FontScaleX = 1; C.FontScaleY = 1; } // NADES if ( !bLightHud ) DrawSpriteWidget(C, GrenadeBG); DrawSpriteWidget(C, GrenadeIcon); DrawNumericWidget(C, GrenadeDigits, DigitsSmall); if ( bDisplayQuickSyringe && !ClassIsChildOf(OwnerWeaponClass, class'Syringe') ) DrawQuickSyringe(C); if ( OwnerWeaponClass != none ) { if ( KFMedicGun(OwnerWeapon) != none ) { MedicGunDigits.Value = KFMedicGun(OwnerWeapon).ChargeBar() * 100.0; if ( MedicGunDigits.Value * 5 < OwnerWeapon.FireModeClass[1].default.AmmoPerFire ) { MedicGunDigits.Tints[0].R = 128; MedicGunDigits.Tints[0].G = 128; MedicGunDigits.Tints[0].B = 128; } else if ( MedicGunDigits.Value < 100 ) { MedicGunDigits.Tints[0].R = 192; MedicGunDigits.Tints[0].G = 96; MedicGunDigits.Tints[0].B = 96; } else MedicGunDigits.Tints[0] = default.MedicGunDigits.Tints[0]; MedicGunDigits.Tints[0].A = KFHUDAlpha; MedicGunDigits.Tints[1] = MedicGunDigits.Tints[0]; if ( !bLightHud ) DrawSpriteWidget(C, MedicGunBG); DrawSpriteWidget(C, MedicGunIcon); DrawNumericWidget(C, MedicGunDigits, DigitsSmall); } if ( ClassIsChildOf(OwnerWeaponClass, class'Syringe') ) { if ( !bLightHud ) DrawSpriteWidget(C, SyringeBG); DrawSpriteWidget(C, SyringeIcon); DrawNumericWidget(C, SyringeDigits, DigitsSmall); } else if ( ClassIsChildOf(OwnerWeaponClass, class'Welder') ) { if ( !bLightHud ) DrawSpriteWidget(C, WelderBG); DrawSpriteWidget(C, WelderIcon); DrawNumericWidget(C, WelderDigits, DigitsSmall); } else if ( !OwnerWeaponClass.default.bMeleeWeapon && OwnerWeaponClass.default.bConsumesPhysicalAmmo ) { if ( !bLightHud ) DrawSpriteWidget(C, ClipsBG); // if ( ClassIsChildOf(OwnerWeaponClass, class'HuskGun') ) { // ClipsDigits.PosX = 0.873; // DrawNumericWidget(C, ClipsDigits, DigitsSmall); // ClipsDigits.PosX = default.ClipsDigits.PosX; // } // else DrawNumericWidget(C, ClipsDigits, DigitsSmall); if ( ClassIsChildOf(OwnerWeaponClass, class'LAW') ) DrawSpriteWidget(C, LawRocketIcon); else if ( ClassIsChildOf(OwnerWeaponClass, class'Crossbow') ) DrawSpriteWidget(C, ArrowheadIcon); else if ( ClassIsChildOf(OwnerWeaponClass, class'CrossBuzzSaw') ) DrawSpriteWidget(C, SawAmmoIcon); else if ( ClassIsChildOf(OwnerWeaponClass, class'PipeBombExplosive') ) DrawSpriteWidget(C, PipeBombIcon); else if ( ClassIsChildOf(OwnerWeaponClass, class'M79GrenadeLauncher') ) DrawSpriteWidget(C, M79Icon); else if ( OwnerWeaponClass == class'HuskGun' ) // ScrnHuskGun handled differently DrawSpriteWidget(C, HuskAmmoIcon); else if ( ClassIsChildOf(OwnerWeaponClass, class'M99SniperRifle') ) DrawSpriteWidget(C, SingleBulletIcon); else { // Ammo in magazine if ( !bLightHud ) DrawSpriteWidget(C, BulletsInClipBG); DrawNumericWidget(C, BulletsInClipDigits, DigitsSmall); if ( ClassIsChildOf(OwnerWeaponClass, class'Flamethrower') || ClassIsChildOf(OwnerWeaponClass, class'ScrnChainsaw') ) { DrawSpriteWidget(C, FlameIcon); DrawSpriteWidget(C, FlameTankIcon); } else if ( ClassIsChildOf(OwnerWeaponClass, class'Shotgun') || ClassIsChildOf(OwnerWeaponClass, class'BoomStick') || ClassIsChildOf(OwnerWeaponClass, class'Winchester') || ClassIsChildOf(OwnerWeaponClass, class'BenelliShotgun') ) { DrawSpriteWidget(C, SingleBulletIcon); DrawSpriteWidget(C, BulletsInClipIcon); } else if ( ClassIsChildOf(OwnerWeaponClass, class'ZEDGun') || ClassIsChildOf(OwnerWeaponClass, class'ZEDMKIIWeapon') ) { DrawSpriteWidget(C, ClipsIcon); DrawSpriteWidget(C, ZedAmmoIcon); } else if ( ClassIsChildOf(OwnerWeaponClass, class'SealSquealHarpoonBomber') || ClassIsChildOf(OwnerWeaponClass, class'SeekerSixRocketLauncher') ) { DrawSpriteWidget(C, ClipsIcon); DrawSpriteWidget(C, SingleNadeIcon); } else if ( ClassIsChildOf(OwnerWeaponClass, class'M32GrenadeLauncher') ) { DrawSpriteWidget(C, M79Icon); DrawSpriteWidget(C, SingleNadeIcon); } else if ( ClassIsChildOf(OwnerWeaponClass, class'ScrnHuskGun') ) { DrawSpriteWidget(C, HuskAmmoIcon); DrawSpriteWidget(C, ZedAmmoIcon); } else { DrawSpriteWidget(C, ClipsIcon); DrawSpriteWidget(C, BulletsInClipIcon); } } } // FLASHLIGHT if ( OwnerWeapon != none && OwnerWeapon.bTorchEnabled ) { if ( !bLightHud ) DrawSpriteWidget(C, FlashlightBG); DrawNumericWidget(C, FlashlightDigits, DigitsSmall); if ( OwnerWeapon.FlashLight != none && OwnerWeapon.FlashLight.bHasLight ) DrawSpriteWidget(C, FlashlightIcon); else DrawSpriteWidget(C, FlashlightOffIcon); } // SECONDARY AMMO if ( (OwnerWeapon != none && OwnerWeapon.bHasSecondaryAmmo) || (bSpectating && CurClipsSecondary > 0) ) { if ( !bLightHud ) DrawSpriteWidget(C, SecondaryClipsBG); DrawNumericWidget(C, SecondaryClipsDigits, DigitsSmall); DrawSpriteWidget(C, SecondaryClipsIcon); } } // DOSH if ( KFGRI != none && KFGRI.bHUDShowCash ) { DrawSpriteWidget(C, CashIcon); DrawNumericWidget(C, CashDigits, DigitsBig); } // PERK - RELATED STUFF if ( ScrnPerk == none ) return; // EXPERIENCE LEVEL TempSize = 36 * VeterancyMatScaleFactor * 1.4; TempX = C.ClipX * 0.007; TempY = C.ClipY * 0.93 - TempSize; C.DrawColor = WhiteColor; TempLevel = KFPRI.ClientVeteranSkillLevel; if( ClientRep!=None && (TempLevel+1) 0 ) { C.SetPos(TempX, TempY-(Counter*VetStarSize*0.8f)); C.DrawTile(TempStarMaterial, VetStarSize, VetStarSize, 0, 0, TempStarMaterial.MaterialUSize(), TempStarMaterial.MaterialVSize()); if( ++Counter==5 ) { Counter = 0; TempX+=VetStarSize; } --TempLevel; } BonusPerkX = TempX + VetStarSize; TempX = BonusPerkX + (TempSize - VetStarSize); TempY = C.ClipY * 0.93 - TempSize; // bonus level if ( KFPRI != none && ScrnPerk.static.GetClientVeteranSkillLevel(KFPRI) != KFPRI.ClientVeteranSkillLevel ) { TempLevel = ScrnPerk.static.GetClientVeteranSkillLevel(KFPRI); Counter = 0; TempLevel = ScrnPerk.Static.PreDrawPerk(C,TempLevel,TempMaterial,TempStarMaterial); C.SetPos(BonusPerkX, TempY); C.DrawColor = WhiteAlphaColor; C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); TempY += (TempSize - (2.0 * VetStarSize)); while( TempLevel > 0 ) { C.SetPos(TempX, TempY-(Counter*VetStarSize*0.8f)); C.DrawTile(TempStarMaterial, VetStarSize, VetStarSize, 0, 0, TempStarMaterial.MaterialUSize(), TempStarMaterial.MaterialVSize()); if( ++Counter==5 ) { Counter = 0; TempX+=VetStarSize; } -- TempLevel; } } // adjust console message location ConsoleMessagePosX = fmax((TempX + 2*VetStarSize) / C.ClipX, 0.105); ConsoleMessagePosY = default.ConsoleMessagePosY; // AVATAR AND CLAN ICON if ( ScrnPRI != none ) { if ( KFGRI != none && !KFGRI.bWaveInProgress ) { TempMaterial = ScrnPRI.GetSpecialIcon(); if ( TempMaterial != none ) { TempX = C.ClipX * 0.007; TempY = C.ClipY * 0.93 - 2.24*TempSize; // TempX += VetStarSize*2; // TempY = C.ClipY * 0.93 - TempSize; C.SetPos(TempX, TempY); C.DrawColor = WhiteAlphaColor; C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); if ( ScrnPRI.GetClanIcon() != TempMaterial ) { TempMaterial = ScrnPRI.GetClanIcon(); if ( TempMaterial != none ) { C.SetPos(BonusPerkX, TempY); C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); } } } } } } // allows child classes to shift Cool HUD, they need to draw something beneath it simulated function CalcCoolHudCoords(Canvas C, float BaseSize, out float XCenter, out float YBottom) { if ( bCoolHudLeftAlign ) XCenter = BaseSize * (0.6 + CoolIconToBarSize); else XCenter = C.ClipX / 2; YBottom = C.ClipY; } simulated function DrawCoolHud(Canvas C) { local float XL, YL, TempX, TempY, BaseSize, TempSize, Offset, Pct; local float XCenter, YBottom, StatusBarHeight, fZoom; local Material TempMaterial; local byte Counter, TempLevel; local String s; if ( KFPRI == none ) return; // init fZoom = CoolHudScale * C.ClipY/1080; // scale by resolution/aspect ratio BaseSize = 64.f * fZoom; C.Font = GetFontSizeIndex(C, 2*fZoom-8); CalcCoolHudCoords(C, BaseSize, XCenter, YBottom); s = class'ScrnUnicode'.default.Dosh @ int(KFPRI.Score); C.TextSize(s, XL, StatusBarHeight); YBottom -= StatusBarHeight; // perk progress for myself if ( bDrawingBonusLevel && KFPRI.ClientVeteranSkillLevel != ScrnPerk.static.GetClientVeteranSkillLevel(KFPRI) ) { C.DrawColor = C.MakeColor(255, 255, 125, CoolPerkAlpha); C.TextSize(strBonusLevel, XL, YL); C.SetPos(XCenter-XL/2, YBottom); C.DrawText(strBonusLevel); } else { TempLevel = KFPRI.ClientVeteranSkillLevel+1; if ( ClientRep != none && ScrnPerk != none && TempLevel < ClientRep.MaximumLevel ) { bDisplayingProgress = true; if( NextLevelTimer 0 ) DrawBar(C, TempX + Offset, YBottom - 3.2*YL, TempSize - 2*Offset, YL, CurClipsSecondary/MaxAmmoSecondary, C.MakeColor(128, 192, 255, KFHUDAlpha)); else if ( KFMedicGun(OwnerWeapon) != none ) { Pct = KFMedicGun(OwnerWeapon).ChargeBar(); if ( Pct * 500 >= OwnerWeapon.FireModeClass[1].default.AmmoPerFire ) C.DrawColor = C.MakeColor(206, 64, 64, KFHUDAlpha); else C.DrawColor = C.MakeColor(128, 128, 128, KFHUDAlpha); DrawBar(C, TempX + Offset, YBottom - 3.2*YL, TempSize - 2*Offset, YL, KFMedicGun(OwnerWeapon).ChargeBar(), C.DrawColor); } if ( MaxAmmoPrimary > 0 ) { if ( Syringe(OwnerWeapon) != none ) { if ( Syringe(OwnerWeapon).ChargeBar() < 0.5 ) C.DrawColor = C.MakeColor(128, 128, 128, KFHUDAlpha); else C.DrawColor = C.MakeColor(206, 64, 64, KFHUDAlpha); } else C.DrawColor = C.MakeColor(160, 160, 160, KFHUDAlpha); DrawBar(C, TempX + Offset, YBottom - 2.1*YL, TempSize - 2*Offset, YL, CurAmmoPrimary/MaxAmmoPrimary, C.DrawColor); } if ( OwnerWeapon.MagCapacity > 1) { if ( bLowAmmo ) C.DrawColor = C.MakeColor(255, 206, 92, KFHUDAlpha); else C.DrawColor = C.MakeColor(92, 192, 92, KFHUDAlpha); DrawBar(C, TempX + Offset, YBottom - YL, TempSize - 2*Offset, YL, float(CurMagAmmo)/OwnerWeapon.MagCapacity, C.DrawColor); } } } // weight C.DrawColor.R = 192; C.DrawColor.G = 192; C.DrawColor.B = 192; s = int(ScrnPawnOwner.CurrentWeight)$"/"$int(ScrnPawnOwner.MaxCarryWeight)$ " kg"; C.TextSize(s, XL, YL); C.SetPos(TempX + (TempSize-XL)/2, YBottom + StatusBarHeight - YL); C.DrawText(s); // draw nades if ( PlayerGrenade != none ) { C.DrawColor = WhiteAlphaColor; TempLevel = GrenadeDigits.Value; TempX += TempSize; TempMaterial = PlayerGrenade.TraderInfoTexture; if ( TempLevel > 0 && TempMaterial != none ) { Counter = 1; Offset = 0; YL = TempSize * 0.20; TempY = YBottom - YL; while ( TempLevel > 0 ) { C.SetPos(TempX, TempY); C.DrawTile(TempMaterial, YL*2, YL, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); if ( Counter == 5 ) { Counter = 1; TempX += YL + Offset; TempY = YBottom - YL; } else { ++Counter; TempY -= YL; TempY -= Offset; } --TempLevel; } } } // nades } // ammo counter if ( OwnerWeapon != none && !OwnerWeapon.bMeleeWeapon && OwnerWeapon.bConsumesPhysicalAmmo ) { TempX = CoolHudAmmoOffsetX * C.ClipX; TempY = CoolHudAmmoOffsetY * C.ClipY; C.FontScaleX = CoolHudAmmoScale * fZoom; C.FontScaleY = CoolHudAmmoScale * fZoom; C.DrawColor = CoolHudAmmoColor; C.DrawColor.A = KFHUDAlpha; if ( WeaponMaxCharge > 0 ) s = string(int(CurAmmoPrimary)); else if ( OwnerWeapon.MagCapacity > 1 ) s = string(int(CurAmmoPrimary - CurMagAmmo)); else s = " "; C.Font = LoadWaitingFont(1);// 0 - big, 1 - smaller C.TextSize(s, XL, YL); C.SetPos(TempX - XL, TempY - YL); // align bottom right C.DrawText(s); TempX -= XL; TempY -= YL*0.5; if ( WeaponMaxCharge > 0 ) s = string(int(WeaponChargePct*WeaponMaxCharge)); else if ( OwnerWeapon.MagCapacity > 1 ) s = string(CurMagAmmo); else s = string(int(CurAmmoPrimary)); C.Font = LoadWaitingFont(0);// 0 - big, 1 - smaller C.TextSize(s, XL, YL); C.SetPos(TempX - XL, TempY - YL); if ( bLowAmmo || WeaponMaxCharge > 0 ) C.DrawColor = BulletsInClipDigits.Tints[0]; C.DrawText(s); // restore C.FontScaleX = 1.0; C.FontScaleY = 1.0; } } simulated function DrawWeaponName(Canvas C) { local string CurWeaponName; local float XL,YL; if ( PawnOwner == None || bCoolHudActive ) return; if ( PawnOwner.Weapon != none ) CurWeaponName = PawnOwner.Weapon.GetHumanReadableName(); else if ( PlayerOwner.Pawn != PawnOwner && ScrnPawnOwner != none && ScrnPawnOwner.SpecWeapon != none ) CurWeaponName = ScrnPawnOwner.SpecWeapon.default.ItemName; if ( CurWeaponName == "" ) return; C.Font = GetFontSizeIndex(C, -1); C.SetDrawColor(255, 50, 50, KFHUDAlpha); C.Strlen(CurWeaponName, XL, YL); // Diet Hud needs to move the weapon name a little bit or it looks weird if ( !bLightHud ) C.SetPos((C.ClipX * 0.983) - XL, C.ClipY * 0.90); else C.SetPos((C.ClipX * 0.97) - XL, C.ClipY * 0.915); C.DrawText(CurWeaponName); } simulated function UpdateHud() { if( PawnOwner == none ) { super.UpdateHud(); return; } CalculateAmmo(); if ( OldHealth != HealthDigits.Value || OldArmor != ArmorDigits.Value ) { OldHealth = HealthDigits.Value; OldArmor = ArmorDigits.Value; HealthFading = 255; bHealthFadeOut = CoolHealthFadeOutTime > 0; } if ( ScrnPawnOwner != none ) FlashlightDigits.Value = 100 * (float(ScrnPawnOwner.TorchBatteryLife) / float(ScrnPawnOwner.default.TorchBatteryLife)); //reset to default values ClipsDigits.Tints[0] = default.ClipsDigits.Tints[0]; ClipsDigits.Tints[1] = default.ClipsDigits.Tints[1]; BulletsInClipDigits.Tints[0] = default.BulletsInClipDigits.Tints[0]; BulletsInClipDigits.Tints[1] = default.BulletsInClipDigits.Tints[1]; if ( OwnerWeapon != none ) { if ( WeaponMaxCharge > 0 ) { BulletsInClipDigits.Value = WeaponChargePct * WeaponMaxCharge; BulletsInClipDigits.Tints[0].R = 206 * (1.0-WeaponChargePct); BulletsInClipDigits.Tints[0].G = 206 * WeaponChargePct; BulletsInClipDigits.Tints[0].B = 0; if (WeaponChargePct > 0.9999) BulletsInClipDigits.Tints[0].A = PulseAlpha; BulletsInClipDigits.Tints[1] = BulletsInClipDigits.Tints[0]; } else BulletsInClipDigits.Value = CurMagAmmo; if ( bLowAmmo ) { if ( BulletsInClipDigits.Value == 0 ) { BulletsInClipDigits.Tints[0].R = 192; BulletsInClipDigits.Tints[0].G = 0; BulletsInClipDigits.Tints[0].B = 0; } else { BulletsInClipDigits.Tints[0].R = 192; BulletsInClipDigits.Tints[0].G = 160; BulletsInClipDigits.Tints[0].B = 0; } BulletsInClipDigits.Tints[0].A = PulseAlpha; BulletsInClipDigits.Tints[1] = BulletsInClipDigits.Tints[0]; } if ( PlayerGrenade == none ) FindPlayerGrenade(); if ( PlayerGrenade != none ) GrenadeDigits.Value = PlayerGrenade.AmmoAmount(0); else GrenadeDigits.Value = 0; } else if ( bSpectatingScrn ) { // spectating BulletsInClipDigits.Value = CurMagAmmo; GrenadeDigits.Value = ScrnPawnOwner.SpecNades; } ClipsDigits.Value = CurClipsPrimary; SecondaryClipsDigits.Value = CurClipsSecondary; if( Vehicle(PawnOwner)!=None ) { if( Vehicle(PawnOwner).Driver!=None ) HealthDigits.Value = Vehicle(PawnOwner).Driver.Health; ArmorDigits.Value = PawnOwner.Health; } else { HealthDigits.Value = PawnOwner.Health; ArmorDigits.Value = PawnOwner.ShieldStrength; } // "Poison" the health meter if ( VomitHudTimer > Level.TimeSeconds ) { HealthDigits.Tints[0].R = 196; HealthDigits.Tints[0].G = 206; HealthDigits.Tints[0].B = 0; } else if ( PawnOwner.Health < 50 ) { if ( Level.TimeSeconds < SwitchDigitColorTime ) { HealthDigits.Tints[0].R = 255; HealthDigits.Tints[0].G = 200; HealthDigits.Tints[0].B = 0; } else { HealthDigits.Tints[0].R = 255; HealthDigits.Tints[0].G = 0; HealthDigits.Tints[0].B = 0; if ( Level.TimeSeconds > SwitchDigitColorTime + 0.2 ) SwitchDigitColorTime = Level.TimeSeconds + 0.2; } } else HealthDigits.Tints[0] = default.HealthDigits.Tints[0]; HealthDigits.Tints[1] = HealthDigits.Tints[0]; CashDigits.Value = PawnOwnerPRI.Score; CoolCashDigits.Value = PawnOwnerPRI.Score; WelderDigits.Value = 100 * CurAmmoPrimary/MaxAmmoPrimary; SyringeDigits.Value = WelderDigits.Value; if ( SyringeDigits.Value < 50 ) { SyringeDigits.Tints[0].R = 128; SyringeDigits.Tints[0].G = 128; SyringeDigits.Tints[0].B = 128; } else if ( SyringeDigits.Value < 100 ) { SyringeDigits.Tints[0].R = 192; SyringeDigits.Tints[0].G = 96; SyringeDigits.Tints[0].B = 96; } else SyringeDigits.Tints[0] = default.SyringeDigits.Tints[0]; SyringeDigits.Tints[1] = SyringeDigits.Tints[0]; // bypass ServerPerks and vanilla KF Super(HudBase).UpdateHud(); } simulated function CalculateAmmo() { MaxAmmoPrimary = 1; CurAmmoPrimary = 0; MaxAmmoSecondary = 0; CurClipsSecondary = 0; CurClipsPrimary = 0; bLowAmmo = false; WeaponChargePct = 0; WeaponMaxCharge = 0; CurMagAmmo = 0; if ( PawnOwner == None ) return; if ( OwnerWeapon != none ) { OwnerWeapon.GetAmmoCount(MaxAmmoPrimary,CurAmmoPrimary); CurMagAmmo = OwnerWeapon.MagAmmoRemaining; if( OwnerWeapon.bHoldToReload ) CurClipsPrimary = max(CurAmmoPrimary-CurMagAmmo,0); // Single rounds reload, just show the true ammo count. else if ( OwnerWeapon.MagCapacity <= 1 ) CurClipsPrimary = CurAmmoPrimary; else if ( CurAmmoPrimary <= 0 || CurAmmoPrimary <= CurMagAmmo ) CurClipsPrimary = 0; else CurClipsPrimary = ceil((CurAmmoPrimary - CurMagAmmo) / OwnerWeapon.MagCapacity); if( OwnerWeapon.bHasSecondaryAmmo && OwnerWeapon.FireModeClass[1].default.AmmoClass != none ) { OwnerWeapon.GetSecondaryAmmoCount(MaxAmmoSecondary, CurClipsSecondary); } if ( ScrnHuskGun(OwnerWeapon) != none ) { WeaponChargePct = ScrnHuskGun(OwnerWeapon).ChargeAmount; WeaponMaxCharge = ScrnHuskGunFire(OwnerWeapon.GetFireMode(0)).MaxChargeAmmo; } else bLowAmmo = OwnerWeapon.MagCapacity > MinMagCapacity && CurMagAmmo <= max(OwnerWeapon.MagCapacity*LowAmmoPercent, 2); } else if ( ScrnPawnOwner != none && PlayerOwner.Pawn != ScrnPawnOwner && ScrnPawnOwner.SpecWeapon != none ) { CurMagAmmo = ScrnPawnOwner.SpecMagAmmo; CurClipsPrimary = ScrnPawnOwner.SpecMags; CurClipsSecondary = ScrnPawnOwner.SpecSecAmmo; if ( ClassIsChildOf(ScrnPawnOwner.SpecWeapon, class'Welder') ) MaxAmmoPrimary = 300; // lame, but this value is used by welder only } } simulated function SetScoreBoardClass (class ScoreBoardClass) { super.SetScoreBoardClass(ScoreBoardClass); if ( ScoreBoard != none ) ScrnScoreBoardClass = class(ScoreBoard.class); if ( ScrnScoreBoardClass == none ) ScrnScoreBoardClass = class'ScrnScoreBoard'; } exec function TogglePlayerInfo() { bHidePlayerInfo = !bHidePlayerInfo; } exec function PlayerInfoVersion(optional byte value) { if ( value == 0 ) PlayerOwner.Player.Console.Message("ScrN HUD Player Info Version = " $ PlayerInfoVersionNumber, 0); else { if ( PlayerInfoVersionNumber != value ) { PlayerInfoVersionNumber = value; SaveConfig(); } if ( PlayerInfoVersionNumber < 90 ) ScrnDrawPlayerInfoBase = ScrnDrawPlayerInfoClassic; else ScrnDrawPlayerInfoBase = ScrnDrawPlayerInfoNew; } } exec function ToggleHudStyle() { if ( bCoolHud ) { if ( bCoolHudLeftAlign ) bCoolHud = false; else bCoolHudLeftAlign = true; } else { bCoolHud = true; bCoolHudLeftAlign = false; } SaveConfig(); } exec function CoolHudSize(float value) { if ( value <= 0 ) { PlayerConsole.Message("Current Cool HUD Size = " $ CoolHudScale, 0); return; } CoolHudScale = fclamp(value, 1.5, 4.0); SaveConfig(); } exec function CoolHudAmmoSize(float value) { if ( value <= 0 ) { PlayerConsole.Message("Current Cool HUD Ammo Counter Size = " $ CoolHudAmmoScale, 0); return; } CoolHudAmmoScale = fclamp(value, 0.0, 4.0); SaveConfig(); } exec function CoolHudAmmoX(float value) { if ( value <= 0 ) { PlayerConsole.Message("Current Cool HUD Ammo Counter Position: X="$CoolHudAmmoOffsetX $ ". Y="$CoolHudAmmoOffsetY, 0); return; } CoolHudAmmoOffsetX = fclamp(value, 0.0, 1.0); SaveConfig(); } exec function CoolHudAmmoY(float value) { if ( value <= 0 ) { PlayerConsole.Message("Current Cool HUD Ammo Counter Position: X="$CoolHudAmmoOffsetX $ ". Y="$CoolHudAmmoOffsetY, 0); return; } CoolHudAmmoOffsetY = fclamp(value, 0.0, 1.0); SaveConfig(); } function DrawPlayerInfo(Canvas C, Pawn P, float ScreenLocX, float ScreenLocY) { local float Dist; local float OldZ, fZoom; local bool bSameTeam; local KFPlayerReplicationInfo EnemyPRI; if ( bHidePlayerInfo ) return; EnemyPRI = KFPlayerReplicationInfo(P.PlayerReplicationInfo); if ( P == none || EnemyPRI == none || KFPRI == none || KFPRI.bViewingMatineeCinematic ) return; bSameTeam = KFPRI.Team == none || EnemyPRI.Team == none || KFPRI.Team.TeamIndex == EnemyPRI.Team.TeamIndex; HealthBarFullVisDist = default.HealthBarFullVisDist; if ( ScrnPerk != none ) HealthBarFullVisDist *= ScrnPerk.static.GetHealPotency(KFPRI); // medic see HP bars better Dist = vsize(P.Location - PlayerOwner.CalcViewLocation); if ( Dist <= HealthBarFullVisDist ) fZoom = 1.0; else { if ( !bSameTeam ) return; // shorter distance on enemy team fZoom = 1.0 - (Dist - HealthBarFullVisDist) / (HealthBarCutoffDist - HealthBarFullVisDist); if ( fZoom < 0.01 ) return; // too far away } if ( PlayerInfoVersionNumber >= 80 ) { fZoom = 1.0 - 0.5*Dist/HealthBarCutoffDist; if ( ScrnPerk != none ) fZoom *= fclamp(ScrnPerk.static.GetHealPotency(KFPRI), 1.0, 1.5); // larger HP bars for medic fZoom *= PlayerInfoScale; } else fZoom = 1.0; OldZ = C.Z; C.Z = 1; C.Style = ERenderStyle.STY_Alpha; // call delegate function ScrnDrawPlayerInfoBase(C, P, ScreenLocX, ScreenLocY, fZoom, EnemyPRI, bSameTeam); C.Z = OldZ; VetStarSize = default.VetStarSize; // restore from drawing in other places } delegate simulated ScrnDrawPlayerInfoBase(Canvas C, Pawn P, float ScreenLocX, float ScreenLocY, float fZoom, KFPlayerReplicationInfo EnemyPRI, bool bSameTeam); simulated function ScrnDrawPlayerInfoClassic(Canvas C, Pawn P, float ScreenLocX, float ScreenLocY, float fZoom, KFPlayerReplicationInfo EnemyPRI, bool bSameTeam) { local float XL, YL, TempX, TempY, TempSize; local float Offset; local byte BeaconAlpha,Counter; local Material TempMaterial, TempStarMaterial; local byte i, TempLevel; local ScrnHumanPawn EnemyScrnPawn; local ScrnCustomPRI EnemyScrnPRI; // zoom BeaconAlpha = clamp(255*fZoom, 50, KFHUDAlpha); BarLength = default.BarLength * fZoom; BarHeight = default.BarHeight * fZoom; HealthIconSize = default.HealthIconSize * fZoom; ArmorIconSize = HealthIconSize; TempSize = 36.f * VeterancyMatScaleFactor * fZoom; VetStarSize = default.VetStarSize * fZoom; Offset = (TempSize * 0.6) - (HealthIconSize + 2.0); // player name C.Font = GetFontSizeIndex(C, 4*fmin(fZoom,1.0)-8); if ( bSameTeam ) C.SetDrawColor(255, 255, 255, BeaconAlpha); else { C.DrawColor = TextColors[EnemyPRI.Team.TeamIndex]; C.DrawColor.A = BeaconAlpha; } ScrnScoreBoardClass.Static.TextSizeCountrySE(C,EnemyPRI,XL,YL); TempX = ScreenLocX - Offset - (0.5 * BarLength) - HealthIconSize - 2.0; // left pos of health icon ScrnScoreBoardClass.Static.DrawCountryNameSE(C, EnemyPRI, ScreenLocX - Offset - XL/2, ScreenLocY-(YL * 0.75), 0, !bSameTeam); // align center if ( bSameTeam || (ScrnPerk != none && ScrnPerk.static.ShowEnemyHealthBars(KFPRI, EnemyPRI))) { EnemyScrnPawn = ScrnHumanPawn(P); // Draw Tourney Icon only during trader time if ( PlayerInfoVersionNumber >= 81 || (KFGRI != none && !KFGRI.bWaveInProgress) ) { EnemyScrnPRI = class'ScrnCustomPRI'.static.FindMe(EnemyPRI); if ( EnemyScrnPRI != none && EnemyScrnPRI.GetSpecialIcon() != none ) { TempMaterial = EnemyScrnPRI.GetSpecialIcon(); TempX -= TempSize + 2.0; TempY = ScreenLocY - YL*0.75 - TempSize; // just above the name C.SetPos(TempX, TempY); C.SetDrawColor(255,255,255,KFHUDAlpha); C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); } } // perk if ( Class(EnemyPRI.ClientVeteranSkill)!=none && EnemyPRI.ClientVeteranSkill.default.OnHUDIcon!=none ) { TempX = ScreenLocX + ((BarLength + HealthIconSize) * 0.5) - (TempSize * 0.25) - Offset; TempY = ScreenLocY - YL - (TempSize * 0.75); C.DrawColor.A = BeaconAlpha; TempLevel = Class(EnemyPRI.ClientVeteranSkill).Static.PreDrawPerk(C, EnemyPRI.ClientVeteranSkillLevel, TempMaterial,TempStarMaterial); C.SetPos(TempX, TempY); C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); TempX += (TempSize - (VetStarSize * 0.75)); TempY += (TempSize - (VetStarSize * 1.5)); for ( i = 0; i < TempLevel; i++ ) { C.SetPos(TempX, TempY-(Counter*VetStarSize*0.7f)); C.DrawTile(TempStarMaterial, VetStarSize * 0.7, VetStarSize * 0.7, 0, 0, TempStarMaterial.MaterialUSize(), TempStarMaterial.MaterialVSize()); if( ++Counter==5 ) { Counter = 0; TempX+=VetStarSize; } } } // Health if ( P.Health > 0 ) { if ( EnemyScrnPawn != none && EnemyScrnPawn.ClientHealthToGive > 0 ) { DrawKFBarEx(C, ScreenLocX - Offset, (ScreenLocY - YL) - 0.4 * BarHeight, FClamp(P.Health / P.HealthMax, 0, 1), BeaconAlpha, false, FClamp(float(EnemyScrnPawn.ClientHealthToGive) / P.HealthMax, 0, 1.0 - P.Health / P.HealthMax)); } else DrawKFBarEx(C, ScreenLocX - Offset, (ScreenLocY - YL) - 0.4 * BarHeight, FClamp(P.Health / P.HealthMax, 0, 1), BeaconAlpha, false); } // Armor if ( P.ShieldStrength > 0 ) DrawKFBarEx(C, ScreenLocX - Offset, (ScreenLocY - YL) - 1.5 * BarHeight, FClamp(P.ShieldStrength / 100.f, 0, 3), BeaconAlpha, true); } else TempX = ScreenLocX + ((BarLength + HealthIconSize) * 0.5) - (TempSize * 0.25) - Offset; TempX+=VetStarSize; TempY = ScreenLocY - YL - (TempSize * 0.75); C.SetDrawColor(255, 255, 255, BeaconAlpha); if ( P.bIsTyping ) { C.SetPos(TempX, TempY); C.DrawTile(ChatIcon, TempSize, TempSize, 0, 0, ChatIcon.MaterialUSize(), ChatIcon.MaterialVSize()); } else if ( bSameTeam && EnemyScrnPawn != none && EnemyScrnPawn.SpecWeapon != none && PlayerInfoVersionNumber >= 83 ){ // draw weapon icon and ammo status TempMaterial = EnemyScrnPawn.SpecWeapon.default.TraderInfoTexture; if ( TempMaterial != none ) { Offset = TempSize * 0.05; YL = TempSize * 0.15; C.SetPos(TempX, TempY); C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); if (EnemyScrnPawn.AmmoStatus > 0 ) { // AmmoStatus=1 indicates that weapon is empty, but it consumes ammo DrawBar(C, TempX + Offset, ScreenLocY - YL - Offset, TempSize - 2*Offset, YL, (EnemyScrnPawn.AmmoStatus-1)/254.0, C.MakeColor(160, 160, 160, BeaconAlpha)); } } } } simulated function ScrnDrawPlayerInfoNew(Canvas C, Pawn P, float ScreenLocX, float ScreenLocY, float fZoom, KFPlayerReplicationInfo EnemyPRI, bool bSameTeam) { local float XL, YL, TempX, TempY, BaseSize, TempSize, Offset; local float BottomBarHeight; local byte BeaconAlpha; local Material TempMaterial; local ScrnHumanPawn EnemyScrnPawn; local ScrnCustomPRI EnemyScrnPRI; // init EnemyScrnPawn = ScrnHumanPawn(P); fZoom *= C.ClipY/1080; // scale by resolution/aspect ratio //BeaconAlpha = clamp(255*fZoom, 50, KFHUDAlpha); BeaconAlpha = 255; BaseSize = 64.f * fZoom; C.Font = GetFontSizeIndex(C, 4*fmin(fZoom,1.0)-8); C.TextSize("0", XL, BottomBarHeight); ScreenLocY -= BottomBarHeight; // player name if ( bSameTeam ) C.SetDrawColor(255, 255, 255, BeaconAlpha); else { C.DrawColor = TextColors[EnemyPRI.Team.TeamIndex]; C.DrawColor.A = BeaconAlpha; } ScrnScoreBoardClass.Static.TextSizeCountrySE(C,EnemyPRI,XL,YL); ScreenLocY -= YL; ScrnScoreBoardClass.Static.DrawCountryNameSE(C, EnemyPRI, ScreenLocX - XL/2, ScreenLocY, 0, !bSameTeam); // align center // CENTRAL INFO -------------------------------------------------------------------------------- if ( bSameTeam || (ScrnPerk != none && ScrnPerk.static.ShowEnemyHealthBars(KFPRI, EnemyPRI))) DrawCoolBar(C, P, EnemyPRI, ScreenLocX - BaseSize/2, ScreenLocY - BaseSize, BaseSize); // --------------------------------------------------------------------------------------------- C.SetDrawColor(255,255,255,BeaconAlpha); TempSize = BaseSize * CoolIconToBarSize; TempX = ScreenLocX - BaseSize * 0.55 - TempSize; TempY = ScreenLocY - TempSize; C.SetDrawColor(255,255,255,BeaconAlpha); // Avatar EnemyScrnPRI = class'ScrnCustomPRI'.static.FindMe(EnemyPRI); if ( EnemyScrnPRI != none ) { TempMaterial = EnemyScrnPRI.GetSpecialIcon(); if ( TempMaterial != none ) { C.SetPos(TempX, TempY); C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); } } // chat icon TempX = ScreenLocX + BaseSize * 0.55; if ( P.bIsTyping ) { C.SetPos(TempX, TempY); C.DrawTile(ChatIcon, TempSize, TempSize, 0, 0, ChatIcon.MaterialUSize(), ChatIcon.MaterialVSize()); } else if ( bSameTeam && EnemyScrnPawn != none && EnemyScrnPawn.SpecWeapon != none ){ // draw weapon icon and ammo status TempMaterial = EnemyScrnPawn.SpecWeapon.default.TraderInfoTexture; if ( TempMaterial != none ) { Offset = TempSize * 0.05; YL = TempSize * 0.15; C.SetPos(TempX, TempY); C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); if (EnemyScrnPawn.AmmoStatus > 0 ) { // AmmoStatus=1 indicates that weapon is empty, but it consumes ammo DrawBar(C, TempX + Offset, ScreenLocY - YL - Offset, TempSize - 2*Offset, YL, (EnemyScrnPawn.AmmoStatus-1)/254.0, C.MakeColor(160, 160, 160, BeaconAlpha)); } } } } simulated function float DrawCoolBar(Canvas C, Pawn P, KFPlayerReplicationInfo PawnPRI, float BaseX, float BaseY, float BaseSize) { local float UpperBound; local float TempSize, TempX, TempY, XL, YL; local float Radius, Angle, Pct, Offset; local material TempMaterial,TempStarMaterial; local byte Counter, TempLevel, PerkLevel; local ScrnHumanPawn EnemyScrnPawn; local int shield; local class EnemyPerk; C.Style = ERenderStyle.STY_Alpha; PassStyle = STY_Alpha; // required for DrawNumericWidget() UpperBound = BaseY; EnemyScrnPawn = ScrnHumanPawn(P); if ( PawnPRI != none ) EnemyPerk = Class(PawnPRI.ClientVeteranSkill); // perk if ( EnemyPerk!=none && EnemyPerk.default.OnHUDIcon!=none ) { TempSize = BaseSize * CoolPerkToBarSize; TempX = BaseX + (BaseSize-TempSize)/2; TempY = BaseY + BaseSize*CoolPerkOffsetY; PerkLevel = EnemyPerk.static.GetClientVeteranSkillLevel(PawnPRI); if ( PerkLevel != PawnPRI.ClientVeteranSkillLevel ) { C.DrawColor.A = CoolPerkAlpha; if ( !bDrawingBonusLevel ) PerkLevel = PawnPRI.ClientVeteranSkillLevel; } TempLevel = EnemyPerk.Static.PreDrawPerk(C, PerkLevel, TempMaterial,TempStarMaterial); C.SetPos(TempX, TempY); C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize()); // draw stars in arc TempSize = BaseSize * CoolStarToBarSize; Radius = BaseSize/2 - TempSize; // center point TempX = BaseX + (BaseSize-TempSize)/2; TempY = BaseY + BaseSize*0.35 - TempSize/2; while (TempLevel > 0) { if (Counter == 0 ) { Counter = 10; Angle = PI/2; Radius += TempSize; if ( TempLevel < 10 && (TempLevel&1) == 1) { YL = Radius; XL = 0; } else { Angle -= CoolStarAngleRad/2; YL = Radius * sin(Angle); XL = Radius * cos(Angle); } UpperBound = fmin(UpperBound, TempY - Radius); } else if (XL > 0) XL = -XL; else { Angle -= CoolStarAngleRad; YL = Radius * sin(Angle); XL = Radius * cos(Angle); } C.SetPos(TempX+XL, TempY - YL); C.DrawTile(TempStarMaterial, TempSize, TempSize, 0, 0, TempStarMaterial.MaterialUSize(), TempStarMaterial.MaterialVSize()); --Counter; --TempLevel; } } // Health TempSize = BaseSize/2; // size in screen units XL = CoolBarSize/2; // size of texture if (P.Health >= P.HealthMax) { C.SetPos(BaseX, BaseY); C.DrawColor = FullHealthColor; C.DrawTile(CoolBarOverlay, TempSize, BaseSize, 0, 0, XL, CoolBarSize); if ( P.Health > P.HealthMax ) { // overcharge Pct = fmax(2.0 - P.Health/P.HealthMax, 0); Offset = CoolHealthBarTop + CoolHealthBarHeight*Pct; YL = Offset * BaseSize / CoolBarSize; C.SetPos(BaseX, BaseY + YL); C.DrawColor = OverchargeHealthColor; C.DrawTile(CoolBarOverlay, TempSize, BaseSize-YL, 0, Offset, XL, CoolBarSize - Offset); } } else { // healed by not restored yet if ( EnemyScrnPawn != none && EnemyScrnPawn.ClientHealthToGive > 0 ) { Pct = fmax(1.0 - (EnemyScrnPawn.Health+float(EnemyScrnPawn.ClientHealthToGive))/P.HealthMax,0); Offset = CoolHealthBarTop + CoolHealthBarHeight*Pct; YL = Offset * BaseSize / CoolBarSize; C.SetPos(BaseX, BaseY + YL); C.DrawColor = HealingBarColor; C.DrawTile(CoolBarOverlay, TempSize, BaseSize-YL, 0, Offset, XL, CoolBarSize - Offset); } // current health Pct = 1.0 - float(P.Health)/P.HealthMax; Offset = CoolHealthBarTop + CoolHealthBarHeight*Pct; YL = Offset * BaseSize / CoolBarSize; C.SetPos(BaseX, BaseY + YL); if ( P.Health < 50 || (P == PlayerOwner.Pawn && VomitHudTimer > Level.TimeSeconds) ) C.DrawColor = LowHealthColor; else if ( EnemyScrnPawn != none && EnemyScrnPawn.Health + EnemyScrnPawn.ClientHealthToGive >=P.HealthMax ) C.DrawColor = FullHealthColor; else C.DrawColor = HealthBarColor; C.DrawTile(CoolBarOverlay, TempSize, BaseSize-YL, 0, Offset, XL, CoolBarSize - Offset); } // armor shield = P.ShieldStrength; if ( shield > 0 ) { C.DrawColor = ArmorBarColor; if ( shield >= 100 ) { // full armor C.SetPos(BaseX+TempSize, BaseY); C.DrawTile(CoolBarOverlay, TempSize, BaseSize, XL, 0, XL, CoolBarSize); shield -= 100; C.DrawColor = BigArmorColor; } if ( shield > 0 ) { Pct = 1.0 - (shield / 100.0); Offset = CoolHealthBarTop + CoolHealthBarHeight*Pct; YL = Offset * BaseSize / CoolBarSize; C.SetPos(BaseX+TempSize, BaseY + YL); C.DrawTile(CoolBarOverlay, TempSize, BaseSize-YL, XL, Offset, XL, CoolBarSize - Offset); } } // bar base C.SetPos(BaseX, BaseY); if ( bCoolHudTeamColor && PawnPRI.Team != none && PawnPRI.Team.TeamIndex < 2 ) C.DrawColor = TeamColors[PawnPRI.Team.TeamIndex]; else C.DrawColor = CoolHudColor; C.DrawTile(CoolBarBase, BaseSize, BaseSize, 0, 0, CoolBarBase.MaterialUSize(), CoolBarBase.MaterialVSize()); // perk text CoolPerkLevelDigits.TextureScale = BaseSize/512.0 * 1080.0/C.ClipY; // NumericWidget scales itself according to resolution CoolPerkLevelDigits.PosX = (BaseX + BaseSize/2) / C.ClipX; CoolPerkLevelDigits.PosY = (BaseY + BaseSize*CoolPerkLevelOffsetY) / C.ClipY; CoolPerkLevelDigits.Value = PerkLevel; CoolPerkLevelDigits.Tints[0] = PerkColor(PerkLevel); CoolPerkLevelDigits.Tints[1] = CoolPerkLevelDigits.Tints[0]; DrawNumericWidget(C, CoolPerkLevelDigits, DigitsSmall); return UpperBound; } simulated function DrawBar(Canvas C, float X, float Y, float W, float H, float Pct, Color BarColor, optional bool bNoBackground, optional bool bVertical, optional int Margin) { if ( !bNoBackground ) { C.SetDrawColor(92, 92, 92, BarColor.A); C.SetPos(X, Y); C.DrawTileStretched(WhiteMaterial, W, H); } if ( Pct > 0 ) { if ( Pct > 1.0 ) Pct = 1.0; if ( Margin < 0 ) Margin = 0; else if ( Margin == 0 ) Margin = 1; X += Margin; Y += Margin; W -= 2*Margin; H -= 2*Margin; if ( bVertical ) H *= Pct; else W *= Pct; C.DrawColor = BarColor; C.SetPos(X, Y); C.DrawTileStretched(WhiteMaterial, W, H); } } simulated function DrawKFBarEx(Canvas C, float XCentre, float YCentre, float BarPercentage, byte BarAlpha, optional bool bArmor, optional float BarPercentage2) { C.SetDrawColor(92, 92, 92, BarAlpha); C.SetPos(XCentre - 0.5 * BarLength, YCentre - 0.5 * BarHeight); C.DrawTileStretched(WhiteMaterial, BarLength, BarHeight); if ( bArmor ) { C.SetDrawColor(255, 255, 255, BarAlpha); C.SetPos(XCentre - (0.5 * BarLength) - ArmorIconSize - 2.0, YCentre - (ArmorIconSize * 0.5)); C.DrawTile(ArmorIcon.WidgetTexture, ArmorIconSize, ArmorIconSize, 0, 0, ArmorIcon.WidgetTexture.MaterialUSize(), ArmorIcon.WidgetTexture.MaterialVSize()); C.SetDrawColor(0, 0, 255, BarAlpha); if ( BarPercentage > 1.0 ) { C.DrawColor = BigArmorColor; BarPercentage -= 1.0; } else C.DrawColor = ArmorBarColor; } else { C.SetDrawColor(255, 255, 255, BarAlpha); C.SetPos(XCentre - (0.5 * BarLength) - HealthIconSize - 2.0, YCentre - (HealthIconSize * 0.5)); C.DrawTile(HealthIcon.WidgetTexture, HealthIconSize, HealthIconSize, 0, 0, HealthIcon.WidgetTexture.MaterialUSize(), HealthIcon.WidgetTexture.MaterialVSize()); if ( PlayerInfoVersionNumber >= 80 && BarPercentage + BarPercentage2 >= 1.0 ) C.DrawColor = FullHealthColor; else C.DrawColor = HealthBarColor; } C.DrawColor.A = BarAlpha; C.SetPos(XCentre - (0.5 * BarLength) + 1.0, YCentre - (0.5 * BarHeight) + 1.0); C.DrawTileStretched(WhiteMaterial, (BarLength - 2.0) * BarPercentage, BarHeight - 2.0); if ( BarPercentage2 > 0 ) { C.SetDrawColor(255, 128, 128, BarAlpha); C.SetPos(XCentre - (0.5 * BarLength) + 1.0 + (BarLength - 2.0) * BarPercentage, YCentre - (0.5 * BarHeight) + 1.0); C.DrawTileStretched(WhiteMaterial, (BarLength - 2.0) * BarPercentage2, BarHeight - 2.0); } } simulated function DrawBlamedIcon(Canvas C, float XCentre, float YBottom, byte BarAlpha) { C.SetDrawColor(255, 255, 255, BarAlpha); C.SetPos(XCentre - (0.5 * BlamedIconSize), YBottom - BlamedIconSize); C.DrawTile(BlamedIcon.WidgetTexture, BlamedIconSize, BlamedIconSize, 0, 0, BlamedIcon.WidgetTexture.MaterialUSize(), BlamedIcon.WidgetTexture.MaterialVSize()); } simulated function ShowDamage(int Damage, float HitTime, vector HitLocation, byte DamTypeNum) { local color c; DamagePopups[NextDamagePopupIndex].damage = Damage; DamagePopups[NextDamagePopupIndex].HitTime = HitTime; DamagePopups[NextDamagePopupIndex].DamTypeNum = DamTypeNum; DamagePopups[NextDamagePopupIndex].HitLocation = HitLocation; //ser random speed of fading out, so multiple damages in the same hit location don't overlap each other DamagePopups[NextDamagePopupIndex].RandX = 2.0 * frand(); DamagePopups[NextDamagePopupIndex].RandY = 1.0 + frand(); c.A = 255; if ( DamTypeNum == 1 ) { // headshots c.R = 0; c.G = 100; c.B = 255; } else if ( DamTypeNum == 2 ) { // fire DoT c.R = 206; c.G = 103; c.B = 0; } else if ( DamTypeNum == 10 ) { // player-to-player damage c.R = 206; c.G = 0; c.B = 206; } else if ( Damage >= 500 ) { c.R = 0; c.G = 206; c.B = 0; } else if ( Damage >= 175 ) { c.R = 206; c.G = 206; c.B = 0; } /* else if ( Damage >= 100 ){ c.R = 206; c.G = 64; c.B = 103; } */ else if ( Damage > 0 ) { c.R = 206; c.G = 64; c.B = 64; } else { c.R = 127; c.G = 127; c.B = 127; } DamagePopups[NextDamagePopupIndex].FontColor = c; if( ++NextDamagePopupIndex >= DAMAGEPOPUP_COUNT) NextDamagePopupIndex=0; } simulated function DrawDamage(Canvas C) { local int i; local float TimeSinceHit; local vector CameraLocation, CamDir; local rotator CameraRotation; local vector HBScreenPos; local float TextWidth, TextHeight, x; C.GetCameraLocation(CameraLocation, CameraRotation); CamDir = vector(CameraRotation); if ( C.ClipX <= 800 ) DamagePopupFont = 7; else if ( C.ClipX <= 1024 ) DamagePopupFont = 6; else if ( C.ClipX < 1400 ) DamagePopupFont = 5; else if ( C.ClipX < 1700 ) DamagePopupFont = 4; else DamagePopupFont = 3; C.Font = LoadFont(DamagePopupFont); for( i=0; i < DAMAGEPOPUP_COUNT ; i++ ) { TimeSinceHit = Level.TimeSeconds - DamagePopups[i].HitTime; if( TimeSinceHit > DamagePopupFadeOutTime || ( Normal(DamagePopups[i].HitLocation - CameraLocation) dot Normal(CamDir) < 0.1 ) ) //don't draw if player faced back to the hit location continue; HBScreenPos = C.WorldToScreen(DamagePopups[i].HitLocation); C.StrLen(DamagePopups[i].damage, TextWidth, TextHeight); //draw just on the hit location HBScreenPos.Y -= TextHeight/2; HBScreenPos.X -= TextWidth/2; //let numbers to fly up HBScreenPos.Y -= TimeSinceHit * TextHeight * DamagePopups[i].RandY; x = Sin(2*Pi * TimeSinceHit/DamagePopupFadeOutTime) * TextWidth * DamagePopups[i].RandX; // odd numbers start to flying to the right side, even - left // So in situations of decapitaion player could see both damages if ( i % 2 == 0) x *= -1.0; HBScreenPos.X += x; C.DrawColor = DamagePopups[i].FontColor; C.DrawColor.A = 255 * cos(0.5*Pi * TimeSinceHit/DamagePopupFadeOutTime); C.SetPos( HBScreenPos.X, HBScreenPos.Y); C.DrawText(DamagePopups[i].damage); } } simulated function MyPerkChanged(class OldPerk) { // destroy current PerkOverlay, unless new perk has the same one if ( PerkOverlay != none && (ScrnPerk == none || ScrnPerk.default.HUDOverlay != PerkOverlay.class) ) { PerkOverlay.Destroy(); PerkOverlay = none; } if ( PerkOverlay == none && ScrnPerk != none && ScrnPerk.default.HUDOverlay != none ) { PerkOverlay = spawn(ScrnPerk.default.HUDOverlay, self); if ( PerkOverlay != none ) AddHudOverlay(PerkOverlay); } } simulated function LinkActors() { super.LinkActors(); ScrnGRI = ScrnGameReplicationInfo(PlayerOwner.GameReplicationInfo); if ( PawnOwner != none ) { if ( PawnOwner != ScrnPawnOwner ) ScrnPawnOwner = ScrnHumanPawn(PawnOwner); if ( PawnOwner.Weapon != OwnerWeapon ) OwnerWeapon = KFWeapon(PawnOwner.Weapon); // update KFPRI for spectators too if ( KFPRI != PawnOwner.PlayerReplicationInfo ) { KFPRI = KFPlayerReplicationInfo(PawnOwner.PlayerReplicationInfo); ScrnPRI = none; // it will be set later in this code } } else { ScrnPawnOwner = none; OwnerWeapon = none; if ( PlayerOwner != none ) { if ( KFPRI != PlayerOwner.PlayerReplicationInfo ) { KFPRI = KFPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo); ScrnPRI = none; // it will be set later in this code } } else { // wtf? KFPRI = none; ScrnPRI = none; } } // prevent square portrait of standard characters bSpecialPortrait = bSpecialPortrait && PortraitPRI != None && (PortraitPRI.PlayerID == LastPlayerIDTalking || LastPlayerIDTalking == 0); bSpectating = PawnOwner == none || PlayerOwner.Pawn != PawnOwner; bSpectatingScrn = bSpectating && ScrnPawnOwner != none; bSpectatingZED = bSpectating && !bSpectatingScrn && PawnOwner != none && KFMonster(PawnOwner) != none; bCoolHudActive = bCoolHud && !bShowScoreBoard && !bSpectating && ScrnPawnOwner != none; if ( OwnerWeapon != none ) OwnerWeaponClass = OwnerWeapon.Class; else if ( bSpectatingScrn ) OwnerWeaponClass = ScrnPawnOwner.SpecWeapon; if ( KFPRI != none ) { if ( ScrnPRI == none ) ScrnPRI = class'ScrnCustomPRI'.static.FindMe(KFPRI); if ( PawnOwner != none ) { if ( PrevPerk != KFPRI.ClientVeteranSkill ) { ScrnPerk = class(KFPRI.ClientVeteranSkill); MyPerkChanged(PrevPerk); PrevPerk = KFPRI.ClientVeteranSkill; } } } } simulated function Tick(float deltaTime) { super.Tick(deltaTime); if ( BlamedMonsterClass != none ) { BlameCountdown -= deltaTime; if ( BlameCountdown <= 0 ) { BlamedMonsterClass = none; BlameCountdown = default.BlameCountdown; // set for the next blame } } if ( bHealthFadeOut ) { HealthFading -= deltaTime * 255.0 / CoolHealthFadeOutTime; if ( HealthFading <= 0 ) bHealthFadeOut = false; } if ( PulseAlpha < 100 ) PulseAlpha = 250; else PulseAlpha -= PulseRate * deltaTime; if ( bXPBonusFadingOut ) { CoolPerkAlpha -= XPBonusFadeRate * deltaTime; if ( CoolPerkAlpha <= 10) { CoolPerkAlpha = 10; bXPBonusFadingOut = false; bDrawingBonusLevel = !bDrawingBonusLevel; bXPBonusFadingIn = true; } } else if ( bXPBonusFadingIn ) { CoolPerkAlpha += XPBonusFadeRate * deltaTime; if ( CoolPerkAlpha >= 255 ) { CoolPerkAlpha = 255; bXPBonusFadingIn = false; if ( bDrawingBonusLevel ) XPBonusNextPlaseTime = Level.TimeSeconds + BonusLevelShowTime; else XPBonusNextPlaseTime = Level.TimeSeconds + XPLevelShowTime; } } else if ( Level.TimeSeconds > XPBonusNextPlaseTime ) bXPBonusFadingOut = true; } simulated function DrawHealthBar(Canvas C, Actor A, int Health, int MaxHealth, float Height) { local vector CameraLocation, CamDir, TargetLocation, HBScreenPos; local rotator CameraRotation; local float Dist, HealthPct; local color OldDrawColor; // rjp -- don't draw the health bar if menus are open // exception being, the Veterancy menu if ( PlayerOwner.Player.GUIController.bActive && GUIController(PlayerOwner.Player.GUIController).ActivePage.Name != 'GUIVeterancyBinder' ) { return; } OldDrawColor = C.DrawColor; C.GetCameraLocation(CameraLocation, CameraRotation); if ( KFMonster(A) != none && KFMonster(A).bUseExtendedCollision ) TargetLocation = A.Location + vect(0, 0, 1) * (KFMonster(A).ColHeight + KFMonster(A).ColOffset.Z); else TargetLocation = A.Location + vect(0, 0, 1) * A.CollisionHeight; Dist = VSize(TargetLocation - CameraLocation); EnemyHealthBarLength = FMin(default.EnemyHealthBarLength * (float(C.SizeX) / 1024.f),default.EnemyHealthBarLength); EnemyHealthBarHeight = FMin(default.EnemyHealthBarHeight * (float(C.SizeX) / 1024.f),default.EnemyHealthBarHeight); CamDir = vector(CameraRotation); // Check Distance Threshold / behind camera cut off if ( Dist > HealthBarCutoffDist || (Normal(TargetLocation - CameraLocation) dot CamDir) < 0 ) { return; } // Target is located behind camera HBScreenPos = C.WorldToScreen(TargetLocation); if ( HBScreenPos.X <= 0 || HBScreenPos.X >= C.SizeX || HBScreenPos.Y <= 0 || HBScreenPos.Y >= C.SizeY) { return; } if ( FastTrace(TargetLocation, CameraLocation) ) { C.SetDrawColor(192, 192, 192, 255); C.SetPos(HBScreenPos.X - EnemyHealthBarLength * 0.5, HBScreenPos.Y - EnemyHealthBarHeight); C.DrawTileStretched(WhiteMaterial, EnemyHealthBarLength, EnemyHealthBarHeight); HealthPct = 1.0f * Health / MaxHealth; C.SetDrawColor(255, 0, 0, 255); C.SetPos(HBScreenPos.X - EnemyHealthBarLength * 0.5 + 1.0, HBScreenPos.Y - EnemyHealthBarHeight + 1.0); C.DrawTileStretched(WhiteMaterial, (EnemyHealthBarLength - 2.0) * HealthPct, EnemyHealthBarHeight - 2.0); } C.DrawColor = OldDrawColor; } function DrawBlameIcons(Canvas C) { local KFMonster M; local vector CameraLocation, CamDir, TargetLocation, HBScreenPos; local rotator CameraRotation; local float Dist, IconSize; local color OldDrawColor; if ( BlamedMonsterClass == none ) return; // rjp -- don't draw the health bar if menus are open // exception being, the Veterancy menu if ( PlayerOwner.Player.GUIController.bActive && GUIController(PlayerOwner.Player.GUIController).ActivePage.Name != 'GUIVeterancyBinder' ) { return; } OldDrawColor = C.DrawColor; C.GetCameraLocation(CameraLocation, CameraRotation); foreach C.ViewPort.Actor.VisibleCollidingActors(class'KFMonster',M,BlameDrawDistance,C.ViewPort.Actor.CalcViewLocation) { if ( ClassIsChildOf(M.class, BlamedMonsterClass) && M.Health > 0 && !M.Cloaked() ) { if ( M.bUseExtendedCollision) TargetLocation = M.Location + vect(0, 0, 1) * (M.ColHeight + M.ColOffset.Z); else TargetLocation = M.Location + vect(0, 0, 1) * M.CollisionHeight; Dist = VSize(TargetLocation - CameraLocation); IconSize = BlamedIconSize * fmax(0.5, (BlameDrawDistance - Dist) / BlameDrawDistance); IconSize *= float(C.SizeX) / 1024.f; CamDir = vector(CameraRotation); // Check Distance Threshold / behind camera cut off if ( Dist > HealthBarCutoffDist || (Normal(TargetLocation - CameraLocation) dot CamDir) < 0 ) { continue; } // Target is located behind camera HBScreenPos = C.WorldToScreen(TargetLocation); if ( HBScreenPos.X <= 0 || HBScreenPos.X >= C.SizeX || HBScreenPos.Y <= 0 || HBScreenPos.Y >= C.SizeY) { continue; } if ( FastTrace(TargetLocation, CameraLocation) ) { C.SetDrawColor(192, 192, 192, 255); C.SetPos(HBScreenPos.X - IconSize * 0.5, HBScreenPos.Y - IconSize); C.DrawTile(BlamedIcon.WidgetTexture, IconSize, IconSize, 0, 0, BlamedIcon.WidgetTexture.MaterialUSize(), BlamedIcon.WidgetTexture.MaterialVSize()); } } } C.DrawColor = OldDrawColor; } simulated function DrawDirPointer(Canvas C, KFShopDirectionPointer DirPointer, Vector PointAt, int Row, int Col, optional bool bHideText, optional string TextPrefix, optional bool bRightSide) { local color TextColor; local float size; local vector ScreenPos, WorldPos, FixedZPos; local rotator DirPointerRotation; local vector MyLocation; local actor dummy; if ( DirPointer == none ) return; if ( bHideHud ) { DirPointer.bHidden = true; return; } TextColor = C.DrawColor; size = C.SizeX / 16.0; if ( bRightSide ) ScreenPos.X = c.ClipX - size * (0.8 + Row*2.1); else ScreenPos.X = size * (0.8 + Row*2.1); ScreenPos.Y = size * (1.0 + Col*1.5); WorldPos = PlayerOwner.Player.Console.ScreenToWorld(ScreenPos) * 10.f * (PlayerOwner.default.DefaultFOV / PlayerOwner.FovAngle) + PlayerOwner.CalcViewLocation; DirPointer.SetLocation(WorldPos); // Let's check for a real Z difference (i.e. different floor) doesn't make sense to rotate the arrow // only because the trader is a midget or placed slightly wrong if ( PawnOwner != none ) MyLocation = PawnOwner.Location; else PlayerOwner.PlayerCalcView(dummy, MyLocation, DirPointerRotation); if ( PointAt.Z > MyLocation.Z + 50.f || PointAt.Z < MyLocation.Z - 50.f ) { DirPointerRotation = rotator(PointAt - MyLocation); } else { FixedZPos = PointAt; FixedZPos.Z = MyLocation.Z; DirPointerRotation = rotator(FixedZPos - MyLocation); } DirPointer.SetRotation(DirPointerRotation); C.DrawActor(None, False, True); // Clear Z. DirPointer.bHidden = false; C.DrawActor(DirPointer, False, false); DirPointer.bHidden = true; C.DrawColor = TextColor; if ( !bHideText ) { C.SetPos(ScreenPos.X, ScreenPos.Y + size * 0.5); DrawPointerDistance(C, PointAt, TextPrefix, MyLocation); } } // must be called only from DrawDirPointer! protected simulated function DrawPointerDistance(Canvas C, Vector PointAt, string TextPrefix, Vector MyLocation) { local int FontSize; local float XL, YL; local string S; S = TextPrefix $ int(VSize(PointAt - MyLocation) / 50) $ DistanceUnitString; if ( C.ClipX <= 800 ) FontSize = 7; else if ( C.ClipX <= 1024 ) FontSize = 6; else if ( C.ClipX < 1400 ) FontSize = 5; else if ( C.ClipX < 1700 ) FontSize = 4; else FontSize = 3; C.Font = LoadFont(FontSize); C.StrLen(S, XL, YL); C.CurX -= XL/2; C.DrawText(S); } function DisplayPortrait(PlayerReplicationInfo PRI) { local Material NewPortrait; local ScrnCustomPRI CPRI; if ( LastPlayerIDTalking > 0 ) return; CPRI = class'ScrnCustomPRI'.static.FindMe(PRI); if ( CPRI != none ) NewPortrait = CPRI.GetAvatar(); if ( NewPortrait != none ) bSpecialPortrait = true; else { NewPortrait = PRI.GetPortrait(); bSpecialPortrait = false; } if ( NewPortrait == None ) return; if ( Portrait == None ) PortraitX = 1; Portrait = NewPortrait; PortraitTime = Level.TimeSeconds + 3; PortraitPRI = PRI; } // seems like I'm the first who removed that bloody "final" mark -- PooSH simulated function DrawPortraitSE( Canvas C ) { local float PortraitWidth, PortraitHeight, Margin, XL, YL, X, Y; local int FontIdx; local ScrnCustomPRI PortraitScrnPRI; local Material M; PortraitWidth = 0.125 * C.ClipY; if ( bSpecialPortrait && Portrait != TraderPortrait ) PortraitHeight = PortraitWidth * Portrait.MaterialVSize() / Portrait.MaterialUSize(); else PortraitHeight = 1.5 * PortraitWidth; Margin = 0.025*PortraitWidth; X = -PortraitWidth * PortraitX + Margin; Y = (C.ClipY - PortraitHeight)/2 + Margin; // name if ( PortraitPRI != None ) { if ( PortraitPRI.Team != None && PortraitPRI.Team.TeamIndex < 2 ) C.DrawColor = TextColors[PortraitPRI.Team.TeamIndex]; FontIdx = -2; do { C.Font = GetFontSizeIndex(C, FontIdx); ScrnScoreBoardClass.Static.TextSizeCountrySE(C,PortraitPRI,XL,YL); }until ( XL <= PortraitWidth || --FontIdx < -8 ); // shift portrait up if it gets overlaped with console messages if ( Y + (1.07 * PortraitHeight + YL) > MsgTopY ) Y = MsgTopY - 1.07 * PortraitHeight - YL; if ( XL > PortraitWidth ) ScrnScoreBoardClass.Static.DrawCountryNameSE(C,PortraitPRI, C.ClipY/256 - PortraitWidth*PortraitX, Y + 1.06 * PortraitHeight); // align left else ScrnScoreBoardClass.Static.DrawCountryNameSE(C,PortraitPRI,C.ClipY/256 - PortraitWidth*PortraitX + (PortraitWidth - XL)/2, Y + 1.06 * PortraitHeight); // align center } else if ( Portrait == TraderPortrait ) { C.DrawColor = WhiteColor; C.Font = GetFontSizeIndex(C, -2); C.TextSize(TraderString, XL, YL); // shift portrait up if it gets overlaped with console messages if ( ConsoleMessagePosY < 0.5 && (Y + 1.07 * PortraitHeight + YL) > MsgTopY ) Y = MsgTopY - 1.07 * PortraitHeight - YL; C.SetPos(C.ClipY / 256 - PortraitWidth * PortraitX + 0.5 * (PortraitWidth - XL), Y + 1.06 * PortraitHeight); C.DrawTextClipped(TraderString,true); } // black background prevents alpha/mask flickering on portraits C.SetPos(X, Y); C.DrawColor = BlackColor; C.DrawTileStretched(WhiteMaterial, PortraitWidth, PortraitHeight); C.DrawColor = WhiteColor; C.SetPos(X, Y); C.DrawTile(Portrait, PortraitWidth, PortraitHeight, 0, 0, Portrait.MaterialUSize(), Portrait.MaterialVSize()); if ( !bSpecialPortrait ) { PortraitScrnPRI = class'ScrnCustomPRI'.static.FindMe(PortraitPRI); if ( PortraitScrnPRI != none ) M = PortraitScrnPRI.GetClanIcon(); if ( M != none && M != Portrait ) { C.SetPos(X + PortraitWidth/2, Y + PortraitHeight - PortraitWidth/2); C.DrawColor.A = 160; C.DrawTile(M, PortraitWidth/2, PortraitWidth/2, 0, 0, M.MaterialUSize(), M.MaterialVSize()); C.DrawColor.A = 255; } } C.DrawColor = C.static.MakeColor(160, 160, 160); C.SetPos(X, Y); C.DrawTile( Material'kf_fx_trip_t.Misc.KFModuNoise', PortraitWidth, PortraitHeight, 0.0, 0.0, 512, 512 ); C.DrawColor = WhiteColor; C.SetPos(X - Margin, Y - Margin); C.DrawTileStretched(texture'InterfaceContent.Menu.BorderBoxA1', PortraitWidth + 2*Margin, PortraitHeight + 2*Margin); } simulated function DrawFirstPersonSpectatorHUD(Canvas C) { local String S; local float TempSize, XL, YL; // player name C.SetDrawColor(200, 200, 200, KFHUDAlpha); C.Font = GetFontSizeIndex(C, -4); C.TextSize(strFollowing, XL, YL); c.SetPos((c.ClipX-XL)/2, 0); c.DrawText(strFollowing); if ( bSpectatingZED ) { s = KFMonster(PawnOwner).MenuName; C.Font = LoadWaitingFont(1); C.SetDrawColor(100, 0, 0, KFHUDAlpha); C.TextSize(s, XL, TempSize); c.SetPos((c.ClipX-XL)/2, YL); c.DrawText(s); } else { C.Font = GetFontSizeIndex(C, 0); C.DrawColor = WhiteAlphaColor; ScrnScoreBoardClass.Static.TextSizeCountrySE(C,PawnOwner.PlayerReplicationInfo,XL,TempSize); ScrnScoreBoardClass.Static.DrawCountryNameSE(C,PawnOwner.PlayerReplicationInfo,(c.ClipX-XL)/2,YL); C.DrawColor = WhiteAlphaColor; // weapon icon if ( OwnerWeaponClass != none && OwnerWeaponClass.default.TraderInfoTexture != none ) { TempSize = c.ClipY * 0.2; C.SetPos((c.ClipX-TempSize)/2, c.ClipY - TempSize); C.DrawTile(OwnerWeaponClass.default.TraderInfoTexture, TempSize, TempSize, 0, 0, OwnerWeaponClass.default.TraderInfoTexture.MaterialUSize(), OwnerWeaponClass.default.TraderInfoTexture.MaterialVSize()); } } } // a lot of copy-paste job, because some devs are using "final" mark too much simulated function DrawSpectatingHud(Canvas C) { local rotator CamRot; local vector CamPos, ViewDir, ScreenPos; local KFPawn KFBuddy; local bool bGameEnded; DrawModOverlay(C); if( bHideHud ) return; PlayerOwner.PostFX_SetActive(0, false); // Grab our View Direction C.GetCameraLocation(CamPos, CamRot); ViewDir = vector(CamRot); // Draw the Name, Health, Armor, and Veterancy above other players (using this way to fix portal's beacon errors). foreach VisibleCollidingActors(Class'KFPawn',KFBuddy,HealthBarCutoffDist,CamPos) { KFBuddy.bNoTeamBeacon = true; if ( KFBuddy.PlayerReplicationInfo!=None && KFBuddy.Health>0 && ((KFBuddy.Location - CamPos) Dot ViewDir)>0.8 ) { ScreenPos = C.WorldToScreen(KFBuddy.Location+vect(0,0,1)*KFBuddy.CollisionHeight); if( ScreenPos.X>=0 && ScreenPos.Y>=0 && ScreenPos.X<=C.ClipX && ScreenPos.Y<=C.ClipY ) DrawPlayerInfo(C, KFBuddy, ScreenPos.X, ScreenPos.Y); } } DrawFadeEffect(C); if ( KFPlayerController(PlayerOwner) != None && KFPlayerController(PlayerOwner).ActiveNote != None ) KFPlayerController(PlayerOwner).ActiveNote = None; bGameEnded = KFGRI != none && KFGRI.EndGameType > 0; if( KFGRI != none && KFGRI.EndGameType > 0 ) { if( KFGRI.EndGameType == 2 ) { DrawEndGameHUD(C, True); DrawStoryHUDInfo(C); } else DrawEndGameHUD(C, False); } if ( PlayerOwner.PlayerReplicationInfo != none && !PlayerOwner.PlayerReplicationInfo.bOnlySpectator ) DrawKFHUDTextElements(C); DisplayLocalMessages(C); if ( bShowScoreBoard && ScoreBoard != None ) ScoreBoard.DrawScoreboard(C); else if ( !bGameEnded && (PlayerOwner.PlayerReplicationInfo == none || PlayerOwner.PlayerReplicationInfo.bOnlySpectator) ) DrawSpecialSpectatingHUD(C); // portrait if ( bShowPortrait && Portrait != None ) DrawPortraitSE(C); // Draw hints if ( bDrawHint ) DrawHint(C); DrawStoryHUDInfo(C); if ( bShowDamages ) DrawDamage(C); } simulated function DrawKFHUDTextElements(Canvas C) { local float XL, YL; local int NumZombies, Min; local string S; local float CircleSize; local float ResScale; if ( PlayerOwner == none || KFGRI == none || !KFGRI.bMatchHasBegun || KFPlayerController(PlayerOwner).bShopping ) return; if( KF_StoryGRI(Level.GRI) != none ) return; // DrawStoryHUDInfo is used instead ResScale = C.SizeX / 1024.0; CircleSize = FMin(128 * ResScale,128); C.FontScaleX = FMin(ResScale,1.f); C.FontScaleY = FMin(ResScale,1.f); // Countdown Text if( !KFGRI.bWaveInProgress || (ScrnGRI != none && ScrnGRI.WaveEndRule == 2 /*RULE_Timeout*/ ) ) { C.SetDrawColor(255, 255, 255, 255); C.SetPos(C.ClipX - CircleSize, 2); C.DrawTile(Material'KillingFloorHUD.HUD.Hud_Bio_Clock_Circle', CircleSize, CircleSize, 0, 0, 256, 256); Min = KFGRI.TimeToNextWave / 60; NumZombies = KFGRI.TimeToNextWave - (Min * 60); S = Eval((Min >= 10), string(Min), "0" $ Min) $ ":" $ Eval((NumZombies >= 10), string(NumZombies), "0" $ NumZombies); C.Font = LoadFont(2); C.Strlen(S, XL, YL); C.SetDrawColor(255, 50, 50, KFHUDAlpha); C.SetPos(C.ClipX - CircleSize/2 - (XL / 2), CircleSize/2 - YL / 2); C.DrawText(S, False); } else { C.SetDrawColor(255, 255, 255, 255); C.SetPos(C.ClipX - CircleSize, 2); C.DrawTile(Material'KillingFloorHUD.HUD.Hud_Bio_Circle', CircleSize, CircleSize, 0, 0, 256, 256); S = string(KFGRI.MaxMonsters); if (ScrnGRI != none) { switch (ScrnGRI.WaveEndRule) { case 3: // RULE_EarnDosh case 5: // RULE_GrabDosh case 6: // RULE_GrabDoshZed C.SetPos(C.ClipX - CircleSize/2 - CircleSize/8, 8); if ( KFPRI != none && KFPRI.Team != none ) { C.DrawColor = TeamColors[KFPRI.Team.TeamIndex]; C.DrawColor.A = 255; } C.DrawTile(Texture'ScrnTex.HUD.Hud_Pound_Symbol_BW', CircleSize/4, CircleSize/4, 0, 0, 64, 64); S = string(ScrnGRI.WaveCounter); break; case 7: // RULE_GrabAmmo C.SetPos(C.ClipX - CircleSize/2 - CircleSize/8, 8); C.SetDrawColor(255, 255, 255, 255); C.DrawTile(ClipsIcon.WidgetTexture, CircleSize/4, CircleSize/4, 0, 0, ClipsIcon.TextureCoords.X2, ClipsIcon.TextureCoords.Y2); S = string(ScrnGRI.WaveCounter); break; } } C.Font = LoadFont(1); C.Strlen(S, XL, YL); if (XL > CircleSize * 0.75) { C.Font = LoadFont(2); C.Strlen(S, XL, YL); } C.SetDrawColor(255, 50, 50, KFHUDAlpha); C.SetPos(C.ClipX - CircleSize/2 - (XL / 2), CircleSize/2 - (YL / 1.5)); C.DrawText(S); } if( KFGRI.bWaveInProgress ) { // Show the number of waves S = WaveString @ string(KFGRI.WaveNumber + 1) $ "/" $ string(KFGRI.FinalWave); C.Font = LoadFont(5); C.Strlen(S, XL, YL); C.SetPos(C.ClipX - CircleSize/2 - (XL / 2), CircleSize/2 + (YL / 2.5)); C.DrawText(S); } C.FontScaleX = 1; C.FontScaleY = 1; if ( KFPRI == none || KFPRI.Team == none || KFPRI.bOnlySpectator || PawnOwner == none ) { return; } // Draw the shop pointer if ( KFGRI.CurrentShop != none && (ScrnGRI == none || ScrnGRI.bTraderArrow) ) { if ( ShopDirPointer == None ) { ShopDirPointer = Spawn(Class'KFShopDirectionPointer'); ShopDirPointer.bHidden = true; } C.DrawColor = TextColors[TeamIndex]; DrawDirPointer(C, ShopDirPointer, KFGRI.CurrentShop.Location, 0, 0, false, strTrader); } } // C&P to add CriticalOverlayTimer simulated function DrawModOverlay( Canvas C ) { local float MaxRBrighten, MaxGBrighten, MaxBBrighten; // We want the overlay to start black, and fade in, almost like the player opened their eyes // BrightFactor = 1.5; // Not too bright. Not too dark. Livens things up just abit // Hook for Optional Vision overlay. - Alex if( PawnOwner==None ) { if( CurrentZone!=None || CurrentVolume!=None ) // Reset everything. { LastR = 0; LastG = 0; LastB = 0; CurrentZone = None; LastZone = None; CurrentVolume = None; LastVolume = None; bZoneChanged = false; SetTimer(0.f, false); } VisionOverlay = default.VisionOverlay; // Dead Players see Red if( !PlayerOwner.IsSpectating() && SpectatorOverlay != none ) { C.SetDrawColor(255, 255, 255, GrainAlpha); C.DrawTile(SpectatorOverlay, C.SizeX, C.SizeY, 0, 0, 1024, 1024); } return; } C.SetPos(0, 0); // if critical, pulsate. otherwise, dont. if ( CriticalOverlayTimer > Level.TimeSeconds ) VisionOverlay = CriticalOverlay; else if ( (PlayerOwner.Pawn==PawnOwner || !PlayerOwner.bBehindView) && Vehicle(PawnOwner)==None && PawnOwner.Health>0 && PawnOwner.Health<(PawnOwner.HealthMax*0.25) ) VisionOverlay = NearDeathOverlay; else VisionOverlay = default.VisionOverlay; // Players can choose to turn this feature off completely. // conversely, setting bDistanceFog = false in a Zone //will cause the code to ignore that zone for a shift in RGB tint if ( VisionOverlay == none || (KFLevelRule != none && !KFLevelRule.bUseVisionOverlay) ) return; // here we determine the maximum "brighten" amounts for each value. CANNOT exceed 255 MaxRBrighten = Round(LastR* (1.0 - (LastR / 255)) - 2) ; MaxGBrighten = Round(LastG* (1.0 - (LastG / 255)) - 2) ; MaxBBrighten = Round(LastB* (1.0 - (LastB / 255)) - 2) ; C.SetDrawColor(LastR + MaxRBrighten, LastG + MaxGBrighten, LastB + MaxBBrighten, GrainAlpha); C.DrawTileScaled(VisionOverlay, C.SizeX, C.SizeY); //,0,0,1024,1024); // Here we change over the Zone. // What happens of importance is // A. Set Old Zone to current // B. Set New Zone // C. Set Color info up for use by Tick() // if we're in a new zone or volume without distance fog...just , dont touch anything. // the physicsvolume check is abit screwy because the player is always in a volume called "DefaultPhyicsVolume" // so we've gotta make sure that the return checks take this into consideration. // This block of code here just makes sure that if we've already got a tint, and we step into a zone/volume without // bDistanceFog, our current tint is not affected. // a. If I'm in a zone and its not bDistanceFog. AND IM NOT IN A PHYSICSVOLUME. Just a zone. // b. If I'm in a Volume if ( !PawnOwner.Region.Zone.bDistanceFog && DefaultPhysicsVolume(PawnOwner.PhysicsVolume)==None && !PawnOwner.PhysicsVolume.bDistanceFog ) return; if ( !bZoneChanged ) { // Grab the most recent zone info from our PRI // Only update if it's different // EDIT: AND HAS bDISTANCEFOG true if ( CurrentZone!=PawnOwner.Region.Zone || (DefaultPhysicsVolume(PawnOwner.PhysicsVolume) == None && CurrentVolume != PawnOwner.PhysicsVolume) ) { if ( CurrentZone != none ) LastZone = CurrentZone; else if ( CurrentVolume != none ) LastVolume = CurrentVolume; // This is for all occasions where we're either in a Levelinfo handled zone // Or a zoneinfo. // If we're in a LevelInfo / ZoneInfo and NOT touching a Volume. Set current Zone if ( PawnOwner.Region.Zone.bDistanceFog && DefaultPhysicsVolume(PawnOwner.PhysicsVolume)!= none && !PawnOwner.Region.Zone.bNoKFColorCorrection ) { CurrentVolume = none; CurrentZone = PawnOwner.Region.Zone; } else if ( DefaultPhysicsVolume(PawnOwner.PhysicsVolume) == None && PawnOwner.PhysicsVolume.bDistanceFog && !PawnOwner.PhysicsVolume.bNoKFColorCorrection) { CurrentZone = none; CurrentVolume = PawnOwner.PhysicsVolume; } if ( CurrentVolume != none ) LastZone = none; else if ( CurrentZone != none ) LastVolume = none; if ( LastZone != none ) { if( LastZone.bNewKFColorCorrection ) { LastR = LastZone.KFOverlayColor.R; LastG = LastZone.KFOverlayColor.G; LastB = LastZone.KFOverlayColor.B; } else { LastR = LastZone.DistanceFogColor.R; LastG = LastZone.DistanceFogColor.G; LastB = LastZone.DistanceFogColor.B; } } else if ( LastVolume != none ) { if( LastVolume.bNewKFColorCorrection ) { LastR = LastVolume.KFOverlayColor.R; LastG = LastVolume.KFOverlayColor.G; LastB = LastVolume.KFOverlayColor.B; } else { LastR = LastVolume.DistanceFogColor.R; LastG = LastVolume.DistanceFogColor.G; LastB = LastVolume.DistanceFogColor.B; } } else if ( LastZone != none && LastVolume != none ) return; if ( LastZone != CurrentZone || LastVolume != CurrentVolume ) { bZoneChanged = true; SetTimer(OverlayFadeSpeed, false); } } } if ( !bTicksTurn && bZoneChanged ) { // Pass it off to the tick now // valueCheckout signifies that none of the three values have been // altered by Tick() yet. // BOUNCE IT BACK! :D ValueCheckOut = 0; bTicksTurn = true; SetTimer(OverlayFadeSpeed, false); } } simulated function DrawSpecialSpectatingHUD(Canvas C) { local float XL, YL; local string S; local int i, d; if ( KFGRI == none || !KFGRI.bMatchHasBegun ) return; C.Font = LoadWaitingFont(SpecHeaderFont); // 0 - big, 1 - smaller C.DrawColor = WhiteColor; C.DrawColor.A = KFHUDAlpha; // draw time, if game is not finished yet if ( KFGRI.EndGameType == 0 && KFGRI.ElapsedTime > 0 ) { // total time C.SetPos(0, 0); C.DrawText(FormatTime(KFGRI.ElapsedTime)); // wave num S = WaveString @ string(KFGRI.WaveNumber + 1); C.TextSize(S, XL, YL); C.SetPos((C.ClipX-XL)*0.5, 0); C.DrawText(S); // number of zeds if ( KFGRI.bWaveInProgress ) S = string(KFGRI.MaxMonsters); else s = FormatTime(KFGRI.TimeToNextWave); C.TextSize(S, XL, YL); C.SetPos(C.ClipX-XL, 0); C.DrawText(S); } // deaths if ( bDrawSpecDeaths ) { d = 0; for ( i = 0; i < KFGRI.PRIArray.Length; i++) { if ( !KFGRI.PRIArray[i].bOnlySpectator ) d += KFGRI.PRIArray[i].Deaths; } if ( d > 0 ) { S = string(d); C.TextSize(S, XL, YL); C.SetPos(c.ClipY*0.01, c.ClipY*0.99 - YL/2); C.DrawTile(ScrnScoreBoardClass.default.DeathIcon, YL/2, YL/2, 0, 0, ScrnScoreBoardClass.default.DeathIcon.MaterialUSize(), ScrnScoreBoardClass.default.DeathIcon.MaterialVSize()); C.SetPos(c.ClipY*0.01 + YL/2, c.ClipY*0.99 - YL); C.DrawText(S); } } } // color tar support simulated function LocalizedMessage( class Message, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject, optional String CriticalString) { local int i; local PlayerReplicationInfo HUDPRI; if( Message == None ) return; if( bIsCinematic && !ClassIsChildOf(Message,class'ActionMessage') ) return; if( CriticalString == "" ) { if ( (PawnOwner != None) && (PawnOwner.PlayerReplicationInfo != None) ) HUDPRI = PawnOwner.PlayerReplicationInfo; else HUDPRI = PlayerOwner.PlayerReplicationInfo; if ( HUDPRI == RelatedPRI_1 ) CriticalString = Message.static.GetRelatedString( Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); else CriticalString = Message.static.GetString( Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); } if( bMessageBeep && Message.default.bBeep ) PlayerOwner.PlayBeepSound(); if( !Message.default.bIsSpecial ) { if ( PlayerOwner.bDemoOwner ) { for( i=0; i= ArrayCount(TextMessages) || TextMessages[i].Text == "" ) break; if ( i > 0 && TextMessages[i-1].Text == CriticalString ) return; } AddTextMessage( CriticalString, Message,RelatedPRI_1 ); return; } i = ArrayCount(LocalMessages); if( Message.default.bIsUnique ) { for( i = 0; i < ArrayCount(LocalMessages); i++ ) { if( LocalMessages[i].Message == None ) continue; if( LocalMessages[i].Message == Message ) break; } } else if ( Message.default.bIsPartiallyUnique || PlayerOwner.bDemoOwner ) { for( i = 0; i < ArrayCount(LocalMessages); i++ ) { if( LocalMessages[i].Message == None ) continue; if( ( LocalMessages[i].Message == Message ) && ( LocalMessages[i].Switch == Switch ) ) break; } } if( i == ArrayCount(LocalMessages) ) { for( i = 0; i < ArrayCount(LocalMessages); i++ ) { if( LocalMessages[i].Message == None ) break; } } if( i == ArrayCount(LocalMessages) ) { for( i = 0; i < ArrayCount(LocalMessages) - 1; i++ ) LocalMessages[i] = LocalMessages[i+1]; } ClearMessage( LocalMessages[i] ); LocalMessages[i].Message = Message; LocalMessages[i].Switch = Switch; LocalMessages[i].RelatedPRI = RelatedPRI_1; LocalMessages[i].RelatedPRI2 = RelatedPRI_2; LocalMessages[i].OptionalObject = OptionalObject; LocalMessages[i].EndOfLife = Message.static.GetLifetime(Switch) + Level.TimeSeconds; if ( class'ScrnBalance'.default.Mut != none ) LocalMessages[i].StringMessage = class'ScrnBalance'.default.Mut.ParseColorTags(CriticalString, RelatedPRI_1); else LocalMessages[i].StringMessage = CriticalString; LocalMessages[i].LifeTime = Message.static.GetLifetime(Switch); } function AddTextMessage(string M, class MessageClass, PlayerReplicationInfo PRI) { local int i; local bool bSetPRI; if ( class'ScrnBalance'.default.Mut != none ) { M = class'ScrnBalance'.default.Mut.ParseColorTags(M, PRI); if ( MessageClass==class'SayMessagePlus' ) { MessageClass = class'ScrnSayMessagePlus'; bSetPRI = true; } else if ( MessageClass==class'TeamSayMessagePlus' ) { MessageClass = class'ScrnTeamSayMessagePlus'; bSetPRI = true; } else if ( MessageClass==class'xDeathMessage' ) MessageClass = class'ScrnDeathMessage'; } else { bSetPRI = MessageClass==class'SayMessagePlus' || MessageClass==class'TeamSayMessagePlus'; } if( bMessageBeep && MessageClass.Default.bBeep ) PlayerOwner.PlayBeepSound(); for( i=0; i= 0) ) { CurrentCrosshairColor = PawnOwner.Weapon.CustomCrosshairColor; CurrentCrosshair = PawnOwner.Weapon.CustomCrosshair; CurrentCrosshairScale = PawnOwner.Weapon.CustomCrosshairScale; if ( PawnOwner.Weapon.CustomCrosshairTextureName != "" ) { if ( PawnOwner.Weapon.CustomCrosshairTexture == None ) { PawnOwner.Weapon.CustomCrosshairTexture = Texture(DynamicLoadObject(PawnOwner.Weapon.CustomCrosshairTextureName,class'Texture')); if ( PawnOwner.Weapon.CustomCrosshairTexture == None ) { log(PawnOwner.Weapon$" custom crosshair texture not found!"); PawnOwner.Weapon.CustomCrosshairTextureName = ""; } } CHTexture = Crosshairs[0]; CHTexture.WidgetTexture = PawnOwner.Weapon.CustomCrosshairTexture; } } else { CurrentCrosshair = CrosshairStyle; CurrentCrosshairColor = CrosshairColor; CurrentCrosshairScale = CrosshairScale; } CurrentCrosshair = Clamp(CurrentCrosshair, 0, Crosshairs.Length - 1); NormalScale = Crosshairs[CurrentCrosshair].TextureScale; if ( CHTexture.WidgetTexture == None ) CHTexture = Crosshairs[CurrentCrosshair]; CHTexture.TextureScale *= CurrentCrosshairScale; for( i = 0; i < ArrayCount(CHTexture.Tints); i++ ) CHTexture.Tints[i] = CurrentCrossHairColor; OldScale = HudScale; HudScale=1; OldW = C.ColorModulate.W; C.ColorModulate.W = 1; DrawSpriteWidget (C, CHTexture); C.ColorModulate.W = OldW; HudScale=OldScale; CHTexture.TextureScale = NormalScale; //DrawEnemyName(C); } exec function DebugZedHealth(bool bEnable) { if ( Level.NetMode == NM_Client && (PlayerOwner.PlayerReplicationInfo == none || !PlayerOwner.PlayerReplicationInfo.bOnlySpectator) ) return; bZedHealthShow = bEnable; } simulated function DrawZedHealth(Canvas C) { local vector CameraLocation, CamDir, TargetLocation, HBScreenPos; local rotator CameraRotation; local float Dist; local float XL, YL; local KFMonster M; local color OldDrawColor; local string s; // rjp -- don't draw the health bar if menus are open // exception being, the Veterancy menu if ( PlayerOwner.Player.GUIController.bActive && GUIController(PlayerOwner.Player.GUIController).ActivePage.Name != 'GUIVeterancyBinder' ) return; OldDrawColor = C.DrawColor; C.Font = GetFontSizeIndex(C, -4); C.GetCameraLocation(CameraLocation, CameraRotation); CamDir = vector(CameraRotation); foreach C.ViewPort.Actor.VisibleCollidingActors(class'KFMonster', M, 1000, C.ViewPort.Actor.CalcViewLocation) { if ( M.Health <= 0 ) continue; TargetLocation = M.Location; if ( M.bUseExtendedCollision ) TargetLocation.Z += M.ColHeight + M.ColOffset.Z; else TargetLocation.Z += M.CollisionHeight; Dist = VSize(TargetLocation - CameraLocation); // Check behind camera cut off if ( (Normal(TargetLocation - CameraLocation) dot CamDir) < 0 ) continue; HBScreenPos = C.WorldToScreen(TargetLocation); if ( HBScreenPos.X <= 0 || HBScreenPos.X >= C.SizeX || HBScreenPos.Y <= 0 || HBScreenPos.Y >= C.SizeY) continue; s = M.Health $ " / " $ int(M.HealthMax + 0.01); C.SetDrawColor(0, 206, 0, 255); C.TextSize(s, XL, YL); C.SetPos(HBScreenPos.X - XL/2, HBScreenPos.Y - YL); C.DrawText(s); if ( M.HeadHealth > 0 ) { s = string(int(M.HeadHealth + 0.01)); C.SetDrawColor(0, 100, 255, 255); C.TextSize(s, XL, YL); C.SetPos(HBScreenPos.X - XL/2, HBScreenPos.Y - YL * 2); C.DrawText(s); } } C.DrawColor = OldDrawColor; } exec function DisableHudHacks() { bCrosshairShow = false; bShowKFDebugXHair = false; bZedHealthShow = false; } exec function SpecHeaderSize(byte size) { if ( size == 0 || size == 1) { SpecHeaderFont = 1 - size; SaveConfig(); } else PlayerOwner.ClientMessage("Header size must 0 (small) or 1 (big)"); } final static function color PerkColor(int PerkLevel) { if ( PerkLevel <= 0 ) return default.PerkColors[0]; PerkLevel--; if ( class'ScrnBalance'.default.Mut.b10Stars ) PerkLevel /= 10; else PerkLevel /= 5; return default.PerkColors[min(PerkLevel, default.PerkColors.length-1)]; } final static function string ColoredPerkLevel(int PerkLevel) { return class'ScrnBalance'.static.ColorStringC(string(PerkLevel), PerkColor(PerkLevel)); } function static Font GetStaticFontSizeIndex(Canvas C, int FontSize) { if ( C.ClipY >= 384 ) FontSize++; if ( C.ClipY >= 480 ) FontSize++; if ( C.ClipY >= 600 ) FontSize++; if ( C.ClipY >= 768 ) FontSize++; if ( C.ClipY >= 900 ) FontSize++; if ( C.ClipY >= 1024 ) FontSize++; return LoadFontStatic(Clamp( 8-FontSize, 0, 8)); } simulated function SetHUDAlpha() { super.SetHUDAlpha(); CoolCashIcon.Tints[0].A = KFHUDAlpha; CoolCashIcon.Tints[1].A = KFHUDAlpha; CoolCashDigits.Tints[0].A = KFHUDAlpha; CoolCashDigits.Tints[1].A = KFHUDAlpha; CoolHudAmmoColor.A = KFHUDAlpha; WhiteAlphaColor.A = KFHUDAlpha; default.WhiteAlphaColor.A = KFHUDAlpha; } simulated function LayoutMessage( out HudLocalizedMessage Message, Canvas C ) { local int FontSize; super.LayoutMessage(Message, C); FontSize = Message.Message.static.GetFontSize(Message.Switch, Message.RelatedPRI, Message.RelatedPRI2, PlayerOwner.PlayerReplicationInfo); if (class(Message.Message) != none && (Message.Switch <= 3 || Message.Switch == 5)) { Message.StringFont = GetWaitingFontSizeIndex(C, FontSize); } } function SelectWeapon() { if ( ScrnHumanPawn(PawnOwner) != none && ScrnHumanPawn(PawnOwner).bQuickMeleeInProgress ) return; // no weapon selection during quick melee super.SelectWeapon(); } defaultproperties { MinMagCapacity=5 LowAmmoPercent=0.250000 texCowboy=Texture'ScrnTex.HUD.CowboyMode' CowboyTileWidth=0.250000 CowboyTileY=0.020000 BlamedIcon=(WidgetTexture=Texture'ScrnTex.HUD.Crap64',RenderStyle=STY_Alpha,TextureCoords=(X2=64,Y2=64),TextureScale=0.500000,PosX=0.950000,PosY=0.500000,ScaleMode=SM_Right,Scale=1.000000,Tints[0]=(B=255,G=255,R=255,A=255),Tints[1]=(B=255,G=255,R=255,A=255)) BlamedIconSize=32.000000 SingleNadeIcon=(WidgetTexture=Texture'KillingFloor2HUD.HUD.Hud_M79',RenderStyle=STY_Alpha,TextureCoords=(X2=64,Y2=64),TextureScale=0.220000,PosX=0.781000,PosY=0.943000,ScaleMode=SM_Right,Scale=1.000000,Tints[0]=(B=255,G=255,R=255,A=255),Tints[1]=(B=255,G=255,R=255,A=255)) TraderGroupColor=(B=128,G=128,R=128,A=255) TraderActiveGroupColor=(B=255,G=192,R=192,A=255) TraderSelectedGroupColor=(B=255,G=192,R=192,A=255) TraderPriceButtonColor=(B=160,G=160,R=160,A=255) TraderPriceButtonDisabledColor=(B=255,G=255,R=255,A=255) TraderPriceButtonSelectedColor=(B=160,G=128,R=255,A=255) CriticalOverlay=Shader'KFX.NearDeathShader' strFollowing="FOLLOWING:" strTrader="Trader: " bCoolHud=True CoolHudScale=2.000000 CoolHudAmmoOffsetX=0.995000 CoolHudAmmoOffsetY=0.950000 CoolHudAmmoScale=0.750000 CoolHudColor=(B=255,G=255,R=255,A=255) CoolHudAmmoColor=(B=160,G=160,R=160,A=200) PlayerInfoVersionNumber=90 PlayerInfoScale=1.000000 CoolBarBase=Texture'ScrnTex.HUD.BarBase' CoolBarOverlay=Texture'ScrnTex.HUD.BarOverlay' CoolBarSize=512 CoolHealthBarTop=30 CoolHealthBarHeight=350 HealthBarColor=(R=192,A=200) HealingBarColor=(B=128,G=128,R=255,A=200) FullHealthColor=(G=192,A=200) OverchargeHealthColor=(B=255,G=255,A=200) LowHealthColor=(G=50,R=210,A=200) ArmorBarColor=(B=200,A=200) BigArmorColor=(B=255,G=255,A=200) CoolPerkToBarSize=0.750000 CoolStarToBarSize=0.125000 CoolStarAngleRad=0.261799 CoolPerkLevelOffsetY=0.870000 CoolIconToBarSize=0.750000 CoolHealthFadeOutTime=10.000000 strBonusLevel="^Bonus Level^" CoolPerkLevelDigits=(RenderStyle=STY_Alpha,DrawPivot=DP_MiddleMiddle,OffsetX=5,OffsetY=-2) CoolCashIcon=(WidgetTexture=Texture'ScrnTex.HUD.Hud_Pound_Symbol_BW',RenderStyle=STY_Alpha,TextureCoords=(X2=64,Y2=64),TextureScale=0.250000,PosY=0.004000,Scale=1.000000,Tints[0]=(B=255,G=255,R=255,A=200),Tints[1]=(B=255,G=255,R=255,A=200)) CoolCashDigits=(RenderStyle=STY_Alpha,TextureScale=0.500000,PosX=0.030000,PosY=0.005000,Tints[0]=(B=160,G=160,R=160,A=200),Tints[1]=(B=160,G=160,R=160,A=200)) PulseRate=450.000000 XPLevelShowTime=30.000000 BonusLevelShowTime=2.000000 XPBonusFadeRate=500.000000 bShowDamages=True DamagePopupFont=4 DamagePopupFadeOutTime=3.000000 bShowSpeed=True SpeedometerX=0.850000 SpeedometerFont=5 BlameCountdown=120.000000 BlameDrawDistance=800.000000 bDrawSpecDeaths=True WhiteAlphaColor=(B=255,G=255,R=255,A=255) PerkColors(0)=(B=200,G=200,R=200,A=255) PerkColors(1)=(B=127,G=255,R=255,A=255) PerkColors(2)=(G=225,A=255) PerkColors(3)=(B=255,G=125,A=255) PerkColors(4)=(B=255,R=178,A=255) PerkColors(5)=(G=128,R=255,A=255) PerkColors(6)=(R=160,A=255) TeamColors(0)=(B=64,G=64,R=255,A=255) TeamColors(1)=(B=198,G=153,R=90,A=255) TextColors(0)=(B=50,G=50,R=255,A=255) TextColors(1)=(B=198,G=139,R=75,A=255) strPendingItems="Waiting for shop items from server: " ChatIcon=Texture'ScrnTex.HUD.ChatIcon' ScrnDrawPlayerInfoBase=ScrnHUD.ScrnDrawPlayerInfoNew WeightDigits=(PosY=0.942000) HealthBarFullVisDist=350.000000 HealthBarCutoffDist=1000.000000 DigitsSmall=(TextureCoords[0]=(X2=32)) }