3366 lines
121 KiB
Ucode
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))
|
|
}
|