rott/kf_sources/ScrnBalanceSrv/Classes/ScrnHUD.uc
2026-07-14 20:27:09 +07:00

3366 lines
121 KiB
Ucode

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<ScrnScoreBoard> ScrnScoreBoardClass; // modder friendly interface
// vars below are set inside LinkActors()
var protected transient class<ScrnVeterancyTypes> ScrnPerk;
var private transient class<KFVeterancyTypes> PrevPerk;
var protected transient ScrnHumanPawn ScrnPawnOwner; // ScrN Pawn we are playing or spectating
var protected transient KFWeapon OwnerWeapon;
var protected transient class<KFWeapon> 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<KFMonster> 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<color> 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)<ClientRep.MaximumLevel ) {
// Draw progress bar.
bDisplayingProgress = true;
if( NextLevelTimer<Level.TimeSeconds ) {
NextLevelTimer = Level.TimeSeconds+3.f;
LevelProgressBar = ScrnPerk.Static.GetTotalProgress(ClientRep,TempLevel+1);
}
ScrnScoreBoardClass.Static.DrawProgressBar(C,TempX,TempY-TempSize*0.12f,TempSize*2.f,TempSize*0.1f,VisualProgressBar);
}
C.DrawColor.A = KFHUDAlpha;
TempLevel = ScrnPerk.Static.PreDrawPerk(C,TempLevel,TempMaterial,TempStarMaterial);
C.SetPos(TempX, TempY);
C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize());
TempX += (TempSize - VetStarSize);
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;
}
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<Level.TimeSeconds ) {
NextLevelTimer = Level.TimeSeconds+3.f;
LevelProgressBar = ScrnPerk.Static.GetTotalProgress(ClientRep,TempLevel);
}
C.DrawColor = WhiteAlphaColor;
if ( KFPRI.ClientVeteranSkillLevel != ScrnPerk.static.GetClientVeteranSkillLevel(KFPRI) )
C.DrawColor.A = CoolPerkAlpha;
ScrnScoreBoardClass.Static.DrawProgressBar(C, XCenter - BaseSize/2,YBottom, BaseSize , StatusBarHeight, VisualProgressBar);
}
// Draw dosh on the top of XP bar
if ( KFGRI != none && KFGRI.bHUDShowCash ) {
C.DrawColor = ScrnScoreBoardClass.default.DoshColor;
C.TextSize(s, XL, YL);
C.SetPos(XCenter-XL/2, YBottom);
C.DrawText(s);
}
}
if ( KFGRI != none && KFGRI.bHUDShowCash && (bShowPoints || !KFGRI.bWaveInProgress) ) {
DrawSpriteWidget(C, CoolCashIcon);
DrawNumericWidget(C, CoolCashDigits, DigitsSmall);
}
// CENTRAL INFO --------------------------------------------------------------------------------
TempY = DrawCoolBar(C, ScrnPawnOwner, KFPRI, XCenter-BaseSize/2, YBottom - BaseSize, BaseSize);
// ---------------------------------------------------------------------------------------------
ConsoleMessagePosX = 0.005;
// adjust console message location
if ( bCoolHudLeftAlign )
ConsoleMessagePosY = TempY/C.ClipY - 0.01;
else
ConsoleMessagePosY = default.ConsoleMessagePosY;
TempSize = BaseSize * CoolIconToBarSize;
TempX = XCenter - BaseSize * 0.55 - TempSize;
TempY = YBottom - TempSize;
C.DrawColor = WhiteAlphaColor;
// Avatar
if ( ScrnPRI != none ) {
TempMaterial = ScrnPRI.GetSpecialIcon();
if ( TempMaterial != none ) {
C.SetPos(TempX, TempY);
C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize());
}
}
// Draw sleed in the middle below avatar
if ( bShowSpeed ) {
s = GetSpeedStr(C) $ " ups";
C.TextSize(s, XL, YL);
C.SetPos(TempX + (TempSize-XL)/2, YBottom + StatusBarHeight - YL);
C.DrawText(s);
}
// chat icon
C.DrawColor = WhiteAlphaColor;
TempX = XCenter + BaseSize * 0.55;
if ( ScrnPawnOwner.bIsTyping ) {
C.SetPos(TempX, TempY);
C.DrawTile(ChatIcon, TempSize, TempSize, 0, 0, ChatIcon.MaterialUSize(), ChatIcon.MaterialVSize());
TempX += TempSize;
}
else {
TempMaterial = none;
if ( OwnerWeapon != none ) {
TempMaterial = OwnerWeapon.TraderInfoTexture;
if ( TempMaterial != none ) {
C.SetPos(TempX, TempY);
C.DrawTile(TempMaterial, TempSize, TempSize, 0, 0, TempMaterial.MaterialUSize(), TempMaterial.MaterialVSize());
}
if ( !OwnerWeapon.bMeleeWeapon ) {
Offset = TempSize * 0.05;
YL = TempSize * 0.10;
if ( OwnerWeapon.bHasSecondaryAmmo && MaxAmmoSecondary > 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<Scoreboard> ScoreBoardClass)
{
super.SetScoreBoardClass(ScoreBoardClass);
if ( ScoreBoard != none )
ScrnScoreBoardClass = class<ScrnScoreBoard>(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<SRVeterancyTypes>(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<SRVeterancyTypes>(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<ScrnVeterancyTypes> EnemyPerk;
C.Style = ERenderStyle.STY_Alpha;
PassStyle = STY_Alpha; // required for DrawNumericWidget()
UpperBound = BaseY;
EnemyScrnPawn = ScrnHumanPawn(P);
if ( PawnPRI != none )
EnemyPerk = Class<ScrnVeterancyTypes>(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<KFVeterancyTypes> 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<ScrnVeterancyTypes>(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<LocalMessage> 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<ConsoleMessageCount; i++ )
if ( 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<LocalMessage> 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<ConsoleMessageCount; i++ )
{
if ( TextMessages[i].Text == "" )
break;
}
if( i == ConsoleMessageCount )
{
for( i=0; i<ConsoleMessageCount-1; i++ )
TextMessages[i] = TextMessages[i+1];
}
TextMessages[i].Text = M;
TextMessages[i].MessageLife = Level.TimeSeconds + MessageClass.Default.LifeTime;
TextMessages[i].TextColor = MessageClass.static.GetConsoleColor(PRI);
if( bSetPRI )
TextMessages[i].PRI = PRI;
else
TextMessages[i].PRI = None;
}
// added support of color messages
function DisplayMessages(Canvas C)
{
local int i, j, XPos, YPos,MessageCount;
local float XL, YL, XXL, YYL;
for( i = 0; i < ConsoleMessageCount; i++ )
{
if ( TextMessages[i].Text == "" )
break;
else if( TextMessages[i].MessageLife < Level.TimeSeconds )
{
TextMessages[i].Text = "";
if( i < ConsoleMessageCount - 1 )
{
for( j=i; j<ConsoleMessageCount-1; j++ )
TextMessages[j] = TextMessages[j+1];
}
TextMessages[j].Text = "";
break;
}
else
MessageCount++;
}
MsgTopY = (ConsoleMessagePosY * HudCanvasScale * C.SizeY) + (((1.0 - HudCanvasScale) / 2.0) * C.SizeY);
if ( PlayerOwner == none || PlayerOwner.PlayerReplicationInfo == none || !PlayerOwner.PlayerReplicationInfo.bWaitingPlayer )
{
XPos = (ConsoleMessagePosX * HudCanvasScale * C.SizeX) + (((1.0 - HudCanvasScale) / 2.0) * C.SizeX);
}
else
{
XPos = (0.005 * HudCanvasScale * C.SizeX) + (((1.0 - HudCanvasScale) / 2.0) * C.SizeX);
}
C.Font = GetConsoleFont(C);
C.DrawColor = LevelActionFontColor;
C.TextSize ("A", XL, YL);
MsgTopY -= YL * MessageCount+1; // DP_LowerLeft
MsgTopY -= YL; // Room for typing prompt
YPos = MsgTopY;
for( i=0; i<MessageCount; i++ )
{
if ( TextMessages[i].Text == "" )
break;
C.SetPos( XPos, YPos );
C.DrawColor = TextMessages[i].TextColor;
YYL = 0;
XXL = 0;
if( TextMessages[i].PRI!=None )
{
XL = ScrnScoreBoardClass.Static.DrawCountryNameSE(C,TextMessages[i].PRI,XPos,YPos);
C.SetPos( XPos+XL, YPos );
}
if( SmileyMsgs.Length!=0 )
DrawSmileyText(TextMessages[i].Text,C,,YYL);
else
C.DrawText(TextMessages[i].Text,false);
YPos += (YL+YYL);
}
}
exec function DebugCrosshair(bool bEnable)
{
if ( Level.NetMode == NM_Client && (PlayerOwner.PlayerReplicationInfo == none || !PlayerOwner.PlayerReplicationInfo.bOnlySpectator) )
return;
bCrosshairShow = bEnable;
bShowKFDebugXHair = bEnable;
}
// copy-pated to remove RODebugMode() -- PooSH
simulated function DrawCrosshair (Canvas C)
{
local float NormalScale;
local int i, CurrentCrosshair;
local float OldScale,OldW, CurrentCrosshairScale;
local color CurrentCrosshairColor;
local SpriteWidget CHtexture;
if ( !bCrosshairShow || !bShowKFDebugXHair )
return;
// one more check to prevent hacks
if ( PlayerOwner.Level.NetMode != NM_Standalone && (PlayerOwner.PlayerReplicationInfo == none || !PlayerOwner.PlayerReplicationInfo.bOnlySpectator) ) {
bCrosshairShow = false;
return;
}
if ( (PawnOwner != None) && (PawnOwner.Weapon != None) && (PawnOwner.Weapon.CustomCrosshair >= 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<WaitingMessage>(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))
}