KF2-Server-Extension/ServerExt/Classes/KFExtendedHUD.uc

1222 lines
35 KiB
Ucode
Raw Normal View History

2017-10-20 02:00:49 +00:00
// Written by Marco
//class KFExtendedHUD extends KFHUDBase;
class KFExtendedHUD extends KFGFxHudWrapper;
var array<Ext_T_MonsterPRI> MyCurrentPet;
struct FDeathMessageType
{
var string Msg,SMsg;
var float MsgTime;
};
var array<FDeathMessageType> DeathMessages;
struct FKillMessageType
{
var bool bDamage,bLocal;
var int Counter;
var Class Type;
var string Name;
var PlayerReplicationInfo OwnerPRI;
var float MsgTime;
var color MsgColor;
};
var transient array<FKillMessageType> KillMessages;
var int HealthBarFullVisDist, HealthBarCutoffDist;
var transient float BestPetXL, BestPetYL;
struct PopupDamageInfo
{
2020-11-28 19:53:57 +00:00
var int Damage;
var float HitTime;
var Vector HitLocation;
var byte Type;
var float RandX, RandY;
var color FontColor;
};
const DAMAGEPOPUP_COUNT = 32;
var PopupDamageInfo DamagePopups[32];
var int NextDamagePopupIndex;
var float DamagePopupFadeOutTime;
2017-10-20 02:00:49 +00:00
struct FNewItemEntry
{
var Texture2D Icon;
var string Item;
var float MsgTime;
};
var transient array<FNewItemEntry> NewItems;
var ExtPlayerReplicationInfo EPRI;
var transient KF2GUIController GUIController;
var transient GUIStyleBase GUIStyle;
var transient array<string> ProgressLines;
var transient float ProgressMsgTime,PLCameraDot;
var transient vector PLCameraLoc,PLCameraDir;
var transient rotator PLCameraRot;
//var Texture2D DownArrowTex,MiddleTex,WaveBossTex,WaveProgTex,TraderTimeTex,SyringeBarTex,ArmorIconTex,BatteryIconTex;
var Texture2D HealthIconTex;
var color BlackBGColor,RedBGColor,HUDTextColor;
var transient array<byte> WasNewlyAdded;
var transient OnlineSubsystem OnlineSub;
var localized string BadConnectionStr;
2017-10-20 02:00:49 +00:00
var transient bool bShowProgress,bProgressDC,bConfirmDisconnect,bMeAdmin,bLoadedInitItems;
simulated function PostBeginPlay()
{
Super.PostBeginPlay();
KFPlayerOwner = KFPlayerController(Owner);
OnlineSub = class'GameEngine'.static.GetOnlineSubsystem();
2020-11-28 20:12:58 +00:00
if (OnlineSub!=None)
2017-10-20 02:00:49 +00:00
{
OnlineSub.AddOnInventoryReadCompleteDelegate(SearchInventoryForNewItem);
SetTimer(60,false,'SearchInventoryForNewItem');
}
SetTimer(300 + FRand()*120.f,false,'CheckForItems');
}
2020-11-28 21:54:57 +00:00
2017-10-20 02:00:49 +00:00
simulated function Destroyed()
{
Super.Destroyed();
NotifyLevelChange();
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
simulated final function NotifyLevelChange(optional bool bMapswitch)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
if (OnlineSub!=None)
2017-10-20 02:00:49 +00:00
{
OnlineSub.ClearOnInventoryReadCompleteDelegate(SearchInventoryForNewItem);
OnlineSub = None;
}
// Send to an empty stage to play the "waiting" game.
2020-11-28 20:12:58 +00:00
if (bMapswitch)
2017-10-20 02:00:49 +00:00
SetTimer(0.5,false,'PendingMapSwitch');
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:12:58 +00:00
simulated function PendingMapswitch ()
2017-10-20 02:00:49 +00:00
{
// Make sure we dont garbage collect the game:
class'MS_Game'.Static.SetReference();
class'MS_PC'.Default.TravelData.PendingURL = WorldInfo.GetAddressURL();
class'MS_PC'.Default.TravelData.PendingSong = ExtPlayerController(Owner).BonusMusic;
class'MS_PC'.Default.TravelData.PendingFX = ExtPlayerController(Owner).BonusFX;
ConsoleCommand("Open KFMainMenu?Game="$PathName(class'MS_Game'));
}
2020-11-28 20:04:55 +00:00
final function AddKillMessage(class<Pawn> Victim, int Value, PlayerReplicationInfo PRI, byte Type)
2017-10-20 02:00:49 +00:00
{
local int i;
local bool bDmg,bLcl;
bDmg = (Type==2);
bLcl = (Type==0);
2020-11-28 20:12:58 +00:00
for (i=0; i<KillMessages.Length; ++i)
if (KillMessages[i].bDamage==bDmg && KillMessages[i].bLocal==bLcl && KillMessages[i].Type==Victim && (bDmg || bLcl || KillMessages[i].OwnerPRI==PRI))
2017-10-20 02:00:49 +00:00
{
KillMessages[i].Counter+=Value;
KillMessages[i].MsgTime = WorldInfo.TimeSeconds;
KillMessages[i].MsgColor = GetMsgColor(bDmg,KillMessages[i].Counter);
return;
}
KillMessages.Length = i+1;
KillMessages[i].bDamage = bDmg;
KillMessages[i].bLocal = bLcl;
KillMessages[i].Counter = Value;
KillMessages[i].Type = Victim;
KillMessages[i].OwnerPRI = PRI;
KillMessages[i].MsgTime = WorldInfo.TimeSeconds;
KillMessages[i].Name = GetNameOf(Victim);
KillMessages[i].MsgColor = GetMsgColor(bDmg,Value);
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
final function AddDeathMessage(string S, string StrippedMsg)
2017-10-20 02:00:49 +00:00
{
DeathMessages.Insert(0,1);
DeathMessages[0].Msg = S;
DeathMessages[0].SMsg = StrippedMsg;
DeathMessages[0].MsgTime = WorldInfo.TimeSeconds;
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
final function ShowProgressMsg(string S, optional bool bDis)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
if (S=="")
2017-10-20 02:00:49 +00:00
{
bShowProgress = false;
return;
}
bShowProgress = true;
ParseStringIntoArray(S,ProgressLines,"|",false);
2020-11-28 20:12:58 +00:00
if (!bProgressDC)
2017-10-20 02:00:49 +00:00
ProgressMsgTime = WorldInfo.TimeSeconds+4.f;
bProgressDC = bDis;
2020-11-28 20:12:58 +00:00
if (bDis)
2017-10-20 02:00:49 +00:00
{
LocalPlayer(KFPlayerOwner.Player).ViewportClient.ViewportConsole.OutputText(Repl(S,"|","\n"));
}
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
static final function string GetNameOf(class<Pawn> Other)
2017-10-20 02:00:49 +00:00
{
local string S;
local class<KFPawn_Monster> KFM;
2017-10-20 02:00:49 +00:00
2020-11-28 20:12:58 +00:00
if (Class<VSZombie>(Other)!=None)
2017-10-20 02:00:49 +00:00
return Class<VSZombie>(Other).Default.ZombieName;
KFM = class<KFPawn_Monster>(Other);
2020-11-28 20:12:58 +00:00
if (KFM!=None && KFM.default.LocalizationKey != '')
return Localize("Zeds", string(KFM.default.LocalizationKey), "KFGame");
2017-10-20 02:00:49 +00:00
2020-11-28 20:12:58 +00:00
if (Other.Default.MenuName!="")
2017-10-20 02:00:49 +00:00
return Other.Default.MenuName;
S = string(Other.Name);
2020-11-28 20:12:58 +00:00
if (Left(S,10)~="KFPawn_Zed")
2017-10-20 02:00:49 +00:00
S = Mid(S,10);
2020-11-28 20:12:58 +00:00
else if (Left(S,7)~="KFPawn_")
2017-10-20 02:00:49 +00:00
S = Mid(S,7);
S = Repl(S,"_"," ");
return S;
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
static final function string GetNameArticle(string S)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
switch (Caps(Left(S,1))) // Check if a vowel, then an.
2017-10-20 02:00:49 +00:00
{
case "A":
case "E":
case "I":
case "O":
case "U":
return "an";
}
return "a";
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
static final function string StripMsgColors(string S)
2017-10-20 02:00:49 +00:00
{
local int i;
2020-11-28 20:12:58 +00:00
while (true)
2017-10-20 02:00:49 +00:00
{
i = InStr(S,Chr(6));
2020-11-28 20:12:58 +00:00
if (i==-1)
2017-10-20 02:00:49 +00:00
break;
S = Left(S,i)$Mid(S,i+2);
}
return S;
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
final function color GetMsgColor(bool bDamage, int Count)
2017-10-20 02:00:49 +00:00
{
local float T;
2020-11-28 20:12:58 +00:00
if (bDamage)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
if (Count>1500)
2017-10-20 02:00:49 +00:00
return MakeColor(148,0,0,255);
2020-11-28 20:12:58 +00:00
else if (Count>1000)
2017-10-20 02:00:49 +00:00
{
T = (Count-1000) / 500.f;
return MakeColor(148,0,0,255)*T + MakeColor(255,0,0,255)*(1.f-T);
}
2020-11-28 20:12:58 +00:00
else if (Count>500)
2017-10-20 02:00:49 +00:00
{
T = (Count-500) / 500.f;
return MakeColor(255,0,0,255)*T + MakeColor(255,255,0,255)*(1.f-T);
}
T = Count / 500.f;
return MakeColor(255,255,0,255)*T + MakeColor(0,255,0,255)*(1.f-T);
}
2020-11-28 20:12:58 +00:00
if (Count>20)
2017-10-20 02:00:49 +00:00
return MakeColor(255,0,0,255);
2020-11-28 20:12:58 +00:00
else if (Count>10)
2017-10-20 02:00:49 +00:00
{
T = (Count-10) / 10.f;
return MakeColor(148,0,0,255)*T + MakeColor(255,0,0,255)*(1.f-T);
}
2020-11-28 20:12:58 +00:00
else if (Count>5)
2017-10-20 02:00:49 +00:00
{
T = (Count-5) / 5.f;
return MakeColor(255,0,0,255)*T + MakeColor(255,255,0,255)*(1.f-T);
}
T = Count / 5.f;
return MakeColor(255,255,0,255)*T + MakeColor(0,255,0,255)*(1.f-T);
}
event PostRender()
{
2020-11-28 20:12:58 +00:00
if (GUIController!=None && PlayerOwner.PlayerInput==None)
2017-10-20 02:00:49 +00:00
GUIController.NotifyLevelChange();
2020-11-28 20:12:58 +00:00
if (KFGRI==None)
2017-10-20 02:00:49 +00:00
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
2020-11-28 20:12:58 +00:00
if (GUIController==None || GUIController.bIsInvalid)
2017-10-20 02:00:49 +00:00
{
GUIController = Class'KF2GUIController'.Static.GetGUIController(PlayerOwner);
2020-11-28 20:12:58 +00:00
if (GUIController!=None)
2017-10-20 02:00:49 +00:00
GUIStyle = GUIController.CurrentStyle;
}
GUIStyle.Canvas = Canvas;
GUIStyle.PickDefaultFontSize(Canvas.ClipY);
DrawDamage();
2017-10-20 02:00:49 +00:00
//RenderKFHUD(); // TODO later...
super.PostRender();
// Camera position.
PlayerOwner.GetPlayerViewPoint(PLCameraLoc,PLCameraRot);
PLCameraDir = vector(PLCameraRot);
PLCameraDot = (PLCameraDir Dot PLCameraLoc);
2020-11-28 20:12:58 +00:00
if (MyCurrentPet.Length>0)
2017-10-20 02:00:49 +00:00
DrawPetInfo();
2020-11-28 20:12:58 +00:00
if (EPRI==None)
2017-10-20 02:00:49 +00:00
EPRI = ExtPlayerReplicationInfo(KFPlayerOwner.PlayerReplicationInfo);
2020-11-28 20:12:58 +00:00
else if (EPRI.RespawnCounter>0)
2017-10-20 02:00:49 +00:00
DrawRespawnCounter();
bMeAdmin = (EPRI!=None && EPRI.AdminType<=1);
2020-11-28 20:12:58 +00:00
if (KillMessages.Length>0)
2017-10-20 02:00:49 +00:00
RenderKillMsg();
2020-11-28 20:12:58 +00:00
if (DeathMessages.Length>0)
2017-10-20 02:00:49 +00:00
RenderDMMessages();
2020-11-28 20:12:58 +00:00
if (NewItems.Length>0)
2017-10-20 02:00:49 +00:00
DrawItemsList();
2020-11-28 20:12:58 +00:00
if (bShowProgress || PlayerOwner.Player==None)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
if (ProgressMsgTime<WorldInfo.TimeSeconds)
2017-10-20 02:00:49 +00:00
{
bShowProgress = false;
2020-11-28 20:12:58 +00:00
if (PlayerOwner.Player==None)
2017-10-20 02:00:49 +00:00
{
2021-01-15 09:02:32 +00:00
ShowProgressMsg("Downloading contents for next map, please wait...|Press [Escape] key to cancel connection!"); // TODO: Localization
2017-10-20 02:00:49 +00:00
RenderProgress();
}
2020-11-28 20:12:58 +00:00
else if (bProgressDC)
2017-10-20 02:00:49 +00:00
KFPlayerOwner.ConsoleCommand("Disconnect");
}
else RenderProgress();
}
2020-11-28 20:12:58 +00:00
if (PlayerOwner.Player==None && OnlineSub!=None)
2017-10-20 02:00:49 +00:00
NotifyLevelChange();
}
2020-11-28 21:54:57 +00:00
2017-10-20 02:00:49 +00:00
simulated function CancelConnection()
{
2020-11-28 20:12:58 +00:00
if (!bConfirmDisconnect)
2017-10-20 02:00:49 +00:00
{
2021-01-15 09:02:32 +00:00
ShowProgressMsg("Are you sure you want to cancel connection?|Press [Escape] again to confirm..."); // TODO: Localization
2017-10-20 02:00:49 +00:00
bConfirmDisconnect = true;
}
else class'Engine'.Static.GetEngine().GameViewport.ConsoleCommand("Disconnect");
}
2020-11-28 21:54:57 +00:00
2017-10-20 02:00:49 +00:00
final function DrawRespawnCounter()
{
local float Sc,XL,YL;
local string S;
Canvas.Font = GUIStyle.PickFont(GUIStyle.DefaultFontSize+1,Sc);
S = "You are about to respawn in "$class'UI_Scoreboard'.Static.FormatTimeSM(EPRI.RespawnCounter);
Canvas.SetDrawColor(250,150,150,255);
Canvas.TextSize(S,XL,YL,Sc,Sc);
Canvas.SetPos((Canvas.ClipX-XL)*0.5,Canvas.ClipY*0.075);
Canvas.DrawText(S,,Sc,Sc);
}
2020-11-28 21:54:57 +00:00
2017-10-20 02:00:49 +00:00
exec function SetShowScores(bool bNewValue)
{
bShowScores = bNewValue;
2020-11-28 20:12:58 +00:00
if (GUIController!=None)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
if (bShowScores)
GUIController.OpenMenu(class'UI_Scoreboard_CD');
else GUIController.CloseMenu(class'UI_Scoreboard_CD');
2017-10-20 02:00:49 +00:00
}
}
2020-11-28 21:54:57 +00:00
2017-10-20 02:00:49 +00:00
final function RenderKillMsg()
{
local float Sc,YL,T,X,Y;
local string S;
local int i;
Canvas.Font = GUIStyle.PickFont(GUIStyle.DefaultFontSize,Sc);
Canvas.TextSize("A",X,YL,Sc,Sc);
X = Canvas.ClipX*0.015;
Y = Canvas.ClipY*0.24;
2020-11-28 20:12:58 +00:00
for (i=0; i<KillMessages.Length; ++i)
2017-10-20 02:00:49 +00:00
{
T = WorldInfo.TimeSeconds-KillMessages[i].MsgTime;
2020-11-28 20:12:58 +00:00
if (T>6.f)
2017-10-20 02:00:49 +00:00
{
KillMessages.Remove(i--,1);
continue;
}
2020-11-28 20:12:58 +00:00
if (KillMessages[i].bDamage)
2017-10-20 02:00:49 +00:00
S = "-"$KillMessages[i].Counter$" HP "$KillMessages[i].Name;
2020-11-28 20:12:58 +00:00
else if (KillMessages[i].bLocal)
2017-10-20 02:00:49 +00:00
S = "+"$KillMessages[i].Counter@KillMessages[i].Name$(KillMessages[i].Counter>1 ? " kills" : " kill");
else S = (KillMessages[i].OwnerPRI!=None ? KillMessages[i].OwnerPRI.GetHumanReadableName() : "Someone")$" +"$KillMessages[i].Counter@KillMessages[i].Name$(KillMessages[i].Counter>1 ? " kills" : " kill");
Canvas.SetPos(X,Y);
Canvas.DrawColor = KillMessages[i].MsgColor;
T = (1.f - (T/6.f)) * 255.f;
Canvas.DrawColor.A = T;
Canvas.DrawText(S,,Sc,Sc);
Y+=YL;
}
}
2020-11-28 21:54:57 +00:00
2017-10-20 02:00:49 +00:00
final function RenderDMMessages()
{
local float Sc,YL,XL,T,Y,X;
local string S;
local int i,j;
local byte a;
Canvas.Font = GUIStyle.PickFont(GUIStyle.DefaultFontSize+1,Sc);
Y = Canvas.ClipY*0.98;
2020-11-28 20:12:58 +00:00
for (i=0; i<DeathMessages.Length; ++i)
2017-10-20 02:00:49 +00:00
{
T = WorldInfo.TimeSeconds-DeathMessages[i].MsgTime;
2020-11-28 20:12:58 +00:00
if (T>6.f)
2017-10-20 02:00:49 +00:00
{
DeathMessages.Remove(i--,1);
continue;
}
// Setup alpha color.
T = (1.f - (T/6.f)) * 255.f;
a = Max(T,1);
Canvas.SetDrawColor(0,255,0,a);
// Get text size and setup start position.
Canvas.TextSize(DeathMessages[i].SMsg,XL,YL,Sc,Sc);
Y-=YL;
X = (Canvas.ClipX-XL)*0.5f;
// Now strip text into color tag pieces.
S = DeathMessages[i].Msg;
2020-11-28 20:12:58 +00:00
while (true)
2017-10-20 02:00:49 +00:00
{
Canvas.SetPos(X,Y);
j = InStr(S,Chr(6));
2020-11-28 20:12:58 +00:00
if (j==-1)
2017-10-20 02:00:49 +00:00
{
Canvas.DrawText(S,,Sc,Sc);
break;
}
2020-11-28 20:12:58 +00:00
if (j>0)
2017-10-20 02:00:49 +00:00
{
Canvas.DrawText(Left(S,j),,Sc,Sc);
Canvas.TextSize(Left(S,j),XL,YL,Sc,Sc);
X+=XL;
}
2020-11-28 20:12:58 +00:00
switch (Mid(S,j+1,1))
2017-10-20 02:00:49 +00:00
{
case "O": // Blue victim color.
Canvas.SetDrawColor(32,32,255,a);
break;
case "M": // Green killmessage color.
Canvas.SetDrawColor(0,255,0,a);
break;
case "K": // Red enemy killer color.
Canvas.SetDrawColor(255,32,32,a);
break;
}
S = Mid(S,j+2);
}
}
}
2020-11-28 21:54:57 +00:00
2017-10-20 02:00:49 +00:00
final function RenderProgress()
{
local float Y,XL,YL,Sc;
local int i;
Canvas.Font = GUIStyle.PickFont(GUIStyle.DefaultFontSize+1,Sc);
2020-11-28 20:12:58 +00:00
if (bProgressDC)
2017-10-20 02:00:49 +00:00
Canvas.SetDrawColor(255,80,80,255);
else Canvas.SetDrawColor(255,255,255,255);
Y = Canvas.ClipY*0.2;
2020-11-28 20:12:58 +00:00
for (i=0; i<ProgressLines.Length; ++i)
2017-10-20 02:00:49 +00:00
{
Canvas.TextSize(ProgressLines[i],XL,YL,Sc,Sc);
Canvas.SetPos((Canvas.ClipX-XL)*0.5,Y);
Canvas.DrawText(ProgressLines[i],,Sc,Sc);
Y+=YL;
}
}
function DrawHUD()
{
2020-01-09 11:05:13 +00:00
local KFPawn_Human KFPH;
local KFPawn_Scripted KFPS;
local vector ViewLocation, ViewVector, PlayerPartyInfoLocation, PawnLocation;
local rotator ViewRotation;
2020-11-28 19:53:57 +00:00
local array<PlayerReplicationInfo> VisibleHumanPlayers;
local array<sHiddenHumanPawnInfo> HiddenHumanPlayers;
2017-10-20 02:00:49 +00:00
local float ThisDot,DotScale;
2020-01-09 11:05:13 +00:00
local vector TargetLocation;
local Actor LocActor;
2017-10-20 02:00:49 +00:00
local KFPawn_Monster M;
local vector V;
local bool bSpec;
2020-11-28 19:53:57 +00:00
// Draw weapon HUD underneath everything else
2020-11-28 20:12:58 +00:00
if (KFPlayerOwner != none && KFPlayerOwner.Pawn != none && KFPlayerOwner.Pawn.Weapon != none)
2020-11-28 19:53:57 +00:00
{
2020-11-28 20:04:55 +00:00
KFPlayerOwner.Pawn.Weapon.DrawHUD(self, Canvas);
2020-11-28 19:53:57 +00:00
}
2020-01-09 11:05:13 +00:00
super.DrawHUD();
2020-11-28 19:53:57 +00:00
// Cache GRI
2020-11-28 20:12:58 +00:00
if (KFGRI == none)
2020-11-28 19:53:57 +00:00
{
2020-11-28 20:04:55 +00:00
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
2020-11-28 19:53:57 +00:00
}
2020-01-09 11:05:13 +00:00
2020-11-28 19:53:57 +00:00
// Don't draw canvas HUD in cinematic mode
2020-11-28 20:12:58 +00:00
if (KFPlayerOwner != none && KFPlayerOwner.bCinematicMode)
2020-01-09 11:05:13 +00:00
{
return;
}
LocActor = KFPlayerOwner.ViewTarget != none ? KFPlayerOwner.ViewTarget : KFPlayerOwner;
2017-10-20 02:00:49 +00:00
// Draw the crosshair for casual mode
2020-11-28 20:12:58 +00:00
if (KFPlayerOwner != none && (bDrawCrosshair || bForceDrawCrosshair || KFPlayerOwner.GetTeamNum() == 255))
{
2020-11-28 19:53:57 +00:00
DrawCrosshair();
}
2017-10-20 02:00:49 +00:00
2020-11-28 19:53:57 +00:00
// Friendly player status
2017-10-20 02:00:49 +00:00
bSpec = (PlayerOwner.PlayerReplicationInfo!=None && PlayerOwner.PlayerReplicationInfo.bOnlySpectator);
2020-11-28 20:12:58 +00:00
if (bSpec || PlayerOwner.GetTeamNum()==0)
2017-10-20 02:00:49 +00:00
{
//Friendly player status
2020-11-28 20:12:58 +00:00
if (!class'ExtPlayerController'.Default.bHideNameBeacons)
2020-11-28 19:53:57 +00:00
{
2020-11-28 20:12:58 +00:00
if (KFPlayerOwner != none)
2020-11-28 19:53:57 +00:00
{
2020-11-28 20:04:55 +00:00
KFPlayerOwner.GetPlayerViewPoint(ViewLocation, ViewRotation);
2020-11-28 19:53:57 +00:00
}
ViewVector = vector(ViewRotation);
Canvas.EnableStencilTest(true);
2020-11-28 20:04:55 +00:00
foreach WorldInfo.AllPawns(class'KFPawn_Human', KFPH)
2020-11-28 19:53:57 +00:00
{
2020-11-28 20:12:58 +00:00
if (KFPH.IsAliveAndWell() && KFPH != KFPlayerOwner.Pawn && KFPH.Mesh.SkeletalMesh != none && KFPH.Mesh.bAnimTreeInitialised)
2020-11-28 19:53:57 +00:00
{
2020-11-28 20:04:55 +00:00
PlayerPartyInfoLocation = KFPH.Mesh.GetPosition() + (KFPH.CylinderComponent.CollisionHeight * vect(0,0,1));
2020-11-28 20:12:58 +00:00
if (`TimeSince(KFPH.Mesh.LastRenderTime) < 0.2f && Normal(PlayerPartyInfoLocation - ViewLocation) dot ViewVector > 0.f)
2020-11-28 19:53:57 +00:00
{
2020-11-28 20:12:58 +00:00
if (DrawFriendlyHumanPlayerInfo(KFPH))
2020-11-28 19:53:57 +00:00
{
2020-11-28 20:04:55 +00:00
VisibleHumanPlayers.AddItem(KFPH.PlayerReplicationInfo);
2020-11-28 19:53:57 +00:00
}
else
{
2020-11-28 20:04:55 +00:00
HiddenHumanPlayers.Insert(0, 1);
2020-11-28 19:53:57 +00:00
HiddenHumanPlayers[0].HumanPawn = KFPH;
HiddenHumanPlayers[0].HumanPRI = KFPH.PlayerReplicationInfo;
}
}
else
{
2020-11-28 20:04:55 +00:00
HiddenHumanPlayers.Insert(0, 1);
2020-11-28 19:53:57 +00:00
HiddenHumanPlayers[0].HumanPawn = KFPH;
HiddenHumanPlayers[0].HumanPRI = KFPH.PlayerReplicationInfo;
}
}
}
foreach WorldInfo.AllPawns(class'KFPawn_Scripted', KFPS)
{
if (KFPS.ShouldShowOnHUD())
{
PlayerPartyInfoLocation = KFPS.Mesh.GetPosition() + (KFPS.CylinderComponent.CollisionHeight * vect(0,0,1));
DrawScriptedPawnInfo(KFPS, Normal(PlayerPartyInfoLocation - ViewLocation) dot ViewVector, `TimeSince(KFPS.Mesh.LastRenderTime) < 0.2f);
}
}
2020-11-28 20:12:58 +00:00
if (!KFGRI.bHidePawnIcons)
2020-11-28 19:53:57 +00:00
{
// Draw hidden players
2020-11-28 20:04:55 +00:00
CheckAndDrawHiddenPlayerIcons(VisibleHumanPlayers, HiddenHumanPlayers);
2020-11-28 19:53:57 +00:00
// Draw last remaining zeds
CheckAndDrawRemainingZedIcons();
//Draw our current objective location
2020-11-28 20:12:58 +00:00
if (KFGRI.CurrentObjective != none && KFGRI.ObjectiveInterface != none)
2020-11-28 19:53:57 +00:00
{
KFGRI.ObjectiveInterface.DrawHUD(self, Canvas);
TargetLocation = KFGRI.ObjectiveInterface.GetIconLocation();
ThisDot = Normal((TargetLocation + (class'KFPawn_Human'.default.CylinderComponent.CollisionHeight * vect(0, 0, 1))) - ViewLocation) dot ViewVector;
if (ThisDot > 0 &&
KFGRI.ObjectiveInterface.ShouldShowObjectiveHUD() &&
(!KFGRI.ObjectiveInterFace.HasObjectiveDrawDistance() || VSizeSq(TargetLocation - LocActor.Location) < MaxDrawDistanceObjective))
{
DrawObjectiveHUD();
}
}
}
Canvas.EnableStencilTest(false);
}
2017-10-20 02:00:49 +00:00
}
2020-11-28 20:12:58 +00:00
else if (KFPawn_Monster(PlayerOwner.Pawn)!=None)
2017-10-20 02:00:49 +00:00
{
// Draw human health auras.
DotScale = Canvas.ClipX*0.2f;
2020-01-09 11:05:13 +00:00
foreach WorldInfo.AllPawns(class'KFPawn_Human', KFPH)
2017-10-20 02:00:49 +00:00
{
2020-01-09 11:05:13 +00:00
PawnLocation = KFPH.Location;
2020-11-28 20:12:58 +00:00
if (IsZero(PawnLocation))
{
continue;
}
ThisDot = (PLCameraDir Dot PawnLocation) - PLCameraDot;
2020-11-28 20:12:58 +00:00
if (KFPH.IsAliveAndWell() && ThisDot>0.f && ThisDot<10000.f)
2017-10-20 02:00:49 +00:00
{
V = Canvas.Project(PawnLocation);
2020-11-28 20:12:58 +00:00
if (V.X<-100 || V.X>(Canvas.SizeX+100) || V.Y<-100 || V.Y>(Canvas.SizeY+100))
2017-10-20 02:00:49 +00:00
continue;
2020-01-09 11:05:13 +00:00
Canvas.DrawColor = GetHPColorScale(KFPH);
2020-11-28 20:12:58 +00:00
if (PlayerOwner.FastTrace(PawnLocation,PLCameraLoc))
2017-10-20 02:00:49 +00:00
ThisDot*=1.75f;
ThisDot = (DotScale/ThisDot)*350.f;
Canvas.SetPos(V.X-ThisDot*0.25f,V.Y-ThisDot*0.5f);
Canvas.DrawTile(Texture2D'VFX_TEX.FX_Glare_01',ThisDot*0.5f,ThisDot,0,0,512,512,,,BLEND_Additive);
}
}
2020-11-28 20:12:58 +00:00
if (!class'ExtPlayerController'.Default.bHideNameBeacons)
2017-10-20 02:00:49 +00:00
{
2020-11-28 19:53:57 +00:00
Canvas.EnableStencilTest(true);
2017-10-20 02:00:49 +00:00
// Draw zed health bars.
foreach WorldInfo.AllPawns(class'KFPawn_Monster', M)
{
ThisDot = (PLCameraDir Dot (M.Location + M.CylinderComponent.CollisionHeight * vect(0,0,1))) - PLCameraDot;
2020-11-28 20:12:58 +00:00
if (ThisDot>0 && ThisDot<8000.f && M.IsAliveAndWell() && M.PlayerReplicationInfo!=None && M!=PlayerOwner.Pawn && (WorldInfo.TimeSeconds - M.Mesh.LastRenderTime) < 0.4f)
2017-10-20 02:00:49 +00:00
DrawFriendlyHUDZ(M);
}
2020-11-28 19:53:57 +00:00
Canvas.EnableStencilTest(false);
2017-10-20 02:00:49 +00:00
}
}
}
2020-11-28 20:04:55 +00:00
simulated static final function color GetHPColorScale(Pawn P)
2017-10-20 02:00:49 +00:00
{
local color C;
2020-11-28 20:12:58 +00:00
if (P.Health<25) // Red
2017-10-20 02:00:49 +00:00
C.R = 255;
2020-11-28 20:12:58 +00:00
else if (P.Health<75) // Yellow -> Red
2017-10-20 02:00:49 +00:00
{
C.G = (P.Health-25) * 5.1f;
C.R = 255;
}
2020-11-28 20:12:58 +00:00
else if (P.Health<100) // Green -> Yellow
2017-10-20 02:00:49 +00:00
{
C.G = 255;
C.R = (100-P.Health) * 10.2f;
}
else C.G = 255;
C.B = 25;
return C;
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
simulated function DrawFriendlyHUDZ(KFPawn_Monster KFPH)
2017-10-20 02:00:49 +00:00
{
local float Percentage;
local float BarHeight, BarLength;
local vector ScreenPos, TargetLocation;
local FontRenderInfo MyFontRenderInfo;
local float FontScale;
2020-11-28 19:53:57 +00:00
local byte FadeAlpha;
2017-10-20 02:00:49 +00:00
2020-11-28 20:04:55 +00:00
MyFontRenderInfo = Canvas.CreateFontRenderInfo(true);
2020-11-28 19:53:57 +00:00
FadeAlpha = DrawToDistance(KFPH);
2017-10-20 02:00:49 +00:00
BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale;
BarHeight = FMin(8.f * (float(Canvas.SizeX) / 1024.f), 8.f) * FriendlyHudScale;
TargetLocation = KFPH.Location + vect(0,0,1) * KFPH.GetCollisionHeight() * 1.2;
ScreenPos = Canvas.Project(TargetLocation);
2020-11-28 20:12:58 +00:00
if (ScreenPos.X < 0 || ScreenPos.X > Canvas.SizeX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.SizeY)
2017-10-20 02:00:49 +00:00
return;
//Draw health bar
Percentage = float(KFPH.Health) / float(KFPH.HealthMax);
2020-01-09 11:05:13 +00:00
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor, FadeAlpha);
2017-10-20 02:00:49 +00:00
//Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
2020-11-28 19:53:57 +00:00
Canvas.DrawColor = PlayerBarTextColor;
Canvas.DrawColor.A = FadeAlpha;
2017-10-20 02:00:49 +00:00
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 2);
2020-11-28 20:04:55 +00:00
Canvas.DrawText(KFPH.PlayerReplicationInfo.PlayerName,,FontScale,FontScale, MyFontRenderInfo);
2017-10-20 02:00:49 +00:00
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
simulated function bool DrawFriendlyHumanPlayerInfo(KFPawn_Human KFPH)
2017-10-20 02:00:49 +00:00
{
local float Percentage;
local float BarHeight, BarLength;
local vector ScreenPos, TargetLocation;
local ExtPlayerReplicationInfo KFPRI;
local FontRenderInfo MyFontRenderInfo;
local float FontScale;
2020-01-09 11:05:13 +00:00
local float ResModifier;
local float PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, PerkIconSize;
local color CurrentArmorColor, CurrentHealthColor, TextColor;
2020-11-28 19:53:57 +00:00
local string S;
local byte FadeAlpha;
2017-10-20 02:00:49 +00:00
2020-01-09 11:05:13 +00:00
ResModifier = WorldInfo.static.GetResolutionBasedHUDScale() * FriendlyHudScale;
2017-10-20 02:00:49 +00:00
KFPRI = ExtPlayerReplicationInfo(KFPH.PlayerReplicationInfo);
2020-11-28 20:12:58 +00:00
if (KFPRI == none)
2020-01-09 11:05:13 +00:00
{
return false;
}
2017-10-20 02:00:49 +00:00
2020-11-28 19:53:57 +00:00
FadeAlpha = DrawToDistance(KFPH);
2020-11-28 20:04:55 +00:00
MyFontRenderInfo = Canvas.CreateFontRenderInfo(true);
2020-01-09 11:05:13 +00:00
BarLength = FMin(PlayerStatusBarLengthMax * (Canvas.ClipX / 1024.f), PlayerStatusBarLengthMax) * ResModifier;
BarHeight = FMin(8.f * (Canvas.ClipX / 1024.f), 8.f) * ResModifier;
2017-10-20 02:00:49 +00:00
2020-11-28 20:04:55 +00:00
TargetLocation = KFPH.Mesh.GetPosition() + (KFPH.CylinderComponent.CollisionHeight * vect(0,0,2.5f));
ScreenPos = Canvas.Project(TargetLocation);
2020-11-28 20:12:58 +00:00
if (ScreenPos.X < 0 || ScreenPos.X > Canvas.ClipX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.ClipY)
2020-01-09 11:05:13 +00:00
{
return false;
}
2017-10-20 02:00:49 +00:00
//Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
2020-01-09 11:05:13 +00:00
// drop shadow for player name text
2020-11-28 19:53:57 +00:00
S = KFPRI.PlayerName;
2020-11-28 20:12:58 +00:00
if (KFPRI.bBot)
2017-10-20 02:00:49 +00:00
{
S = S$" (Bot)";
2020-01-09 11:05:13 +00:00
TextColor = KFPRI.HUDPerkColor;
2017-10-20 02:00:49 +00:00
}
2020-11-28 20:12:58 +00:00
else if (KFPRI.ShowAdminName()) // Admin info.
2017-10-20 02:00:49 +00:00
{
S = S$" ("$KFPRI.GetAdminNameAbr()$")";
2020-01-09 11:05:13 +00:00
TextColor = KFPRI.GetAdminColorC();
2017-10-20 02:00:49 +00:00
}
2020-01-09 11:05:13 +00:00
else TextColor = PlayerBarTextColor;
2020-11-28 19:53:57 +00:00
2020-11-28 20:12:58 +00:00
if (bMeAdmin && KFPRI.FixedData>0)
2017-10-20 02:00:49 +00:00
{
2020-11-28 19:53:57 +00:00
TextColor = MakeColor(255,0,0,255);
2020-01-09 11:05:13 +00:00
S @= "-"$KFPRI.GetDesc();
2017-10-20 02:00:49 +00:00
}
2020-11-28 19:53:57 +00:00
TextColor.A = FadeAlpha;
Canvas.DrawColor = PlayerBarShadowColor;
Canvas.DrawColor.A = FadeAlpha;
2020-01-09 11:05:13 +00:00
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f) + 1, ScreenPos.Y + 8);
Canvas.DrawText(S, , FontScale, FontScale, MyFontRenderInfo);
2020-11-28 19:53:57 +00:00
Canvas.DrawColor = TextColor;
2020-01-09 11:05:13 +00:00
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + 7);
Canvas.DrawText(S, , FontScale, FontScale, MyFontRenderInfo);
//Draw armor bar
Percentage = FMin(float(KFPH.Armor) / float(KFPH.MaxArmor), 100);
CurrentArmorColor = ClassicPlayerInfo ? ClassicArmorColor : ArmorColor;
2020-11-28 19:53:57 +00:00
CurrentArmorColor.A = FadeAlpha;
2020-01-09 11:05:13 +00:00
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight + (36 * FontScale * ResModifier), CurrentArmorColor, FadeAlpha);
2017-10-20 02:00:49 +00:00
2020-01-09 11:05:13 +00:00
//Draw health bar
Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax), 100);
CurrentHealthColor = ClassicPlayerInfo ? ClassicHealthColor : HealthColor;
2020-11-28 19:53:57 +00:00
CurrentHealthColor.A = FadeAlpha;
2020-01-09 11:05:13 +00:00
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight * 2 + (36 * FontScale * ResModifier), CurrentHealthColor, FadeAlpha, true);
2020-11-28 20:12:58 +00:00
if (KFPRI.ECurrentPerk == None)
2017-10-20 02:00:49 +00:00
{
2020-01-09 11:05:13 +00:00
return false;
2017-10-20 02:00:49 +00:00
}
2020-01-09 11:05:13 +00:00
// drop shadow for perk name text
2020-11-28 19:53:57 +00:00
Canvas.DrawColor = PlayerBarShadowColor;
Canvas.DrawColor.A = FadeAlpha;
2020-01-09 11:05:13 +00:00
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f) + 1, ScreenPos.Y + BarHeight * 3 + (36 * FontScale * ResModifier) + 1);
Canvas.DrawText(KFPRI.GetPerkLevelStr()@KFPRI.ECurrentPerk.default.PerkName, , FontScale, FontScale, MyFontRenderInfo);
//Draw perk level and name text
Canvas.DrawColor = PlayerBarTextColor;
2020-11-28 19:53:57 +00:00
Canvas.DrawColor.A = FadeAlpha;
2020-01-09 11:05:13 +00:00
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight * 3 + (36 * FontScale * ResModifier));
Canvas.DrawText(KFPRI.GetPerkLevelStr()@KFPRI.ECurrentPerk.default.PerkName, , FontScale, FontScale, MyFontRenderInfo);
// drop shadow for perk icon
2020-11-28 19:53:57 +00:00
Canvas.DrawColor = PlayerBarShadowColor;
2020-01-09 11:05:13 +00:00
Canvas.DrawColor.A = FadeAlpha;
PerkIconSize = PlayerStatusIconSize * ResModifier;
PerkIconPosX = ScreenPos.X - (BarLength * 0.5f) - PerkIconSize + 1;
PerkIconPosY = ScreenPos.Y + (36 * FontScale * ResModifier) + 1;
SupplyIconPosX = ScreenPos.X + (BarLength * 0.5f) + 1;
SupplyIconPosY = PerkIconPosY + 4 * ResModifier;
DrawPerkIcons(KFPH, PerkIconSize, PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, true);
//draw perk icon
2020-11-28 19:53:57 +00:00
Canvas.DrawColor = PlayerBarIconColor;
2020-01-09 11:05:13 +00:00
Canvas.DrawColor.A = FadeAlpha;
PerkIconPosX = ScreenPos.X - (BarLength * 0.5f) - PerkIconSize;
PerkIconPosY = ScreenPos.Y + (36 * FontScale * ResModifier);
SupplyIconPosX = ScreenPos.X + (BarLength * 0.5f);
SupplyIconPosY = PerkIconPosY + 4 * ResModifier;
DrawPerkIcons(KFPH, PerkIconSize, PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, false);
return true;
2017-10-20 02:00:49 +00:00
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
simulated final function DrawPlayerInfoBar(KFPawn P, float BarPercentage, float BarLength, float BarHeight, float XPos, float YPos, Color BarColor, byte FadeAlpha, optional bool bDrawingHealth)
2017-10-20 02:00:49 +00:00
{
//background for status bar
2020-01-09 11:05:13 +00:00
Canvas.DrawColor = PlayerBarBGColor;
2020-11-28 19:53:57 +00:00
Canvas.DrawColor.A = FadeAlpha;
2017-10-20 02:00:49 +00:00
Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength, BarHeight, 0, 0, 32, 32);
XPos+=1;
YPos+=1;
BarLength-=2;
BarHeight-=2;
//Forground for status bar.
2020-01-09 11:05:13 +00:00
Canvas.DrawColor = BarColor;
2020-11-28 19:53:57 +00:00
Canvas.DrawColor.A = FadeAlpha;
2017-10-20 02:00:49 +00:00
Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength * BarPercentage, BarHeight, 0, 0, 32, 32);
2020-11-28 20:12:58 +00:00
if (bDrawingHealth && ExtHumanPawn(P) != None && P.Health<P.HealthMax && ExtHumanPawn(P).RepRegenHP>0)
2017-10-20 02:00:49 +00:00
{
// Draw to-regen bar.
XPos+=(BarLength * BarPercentage);
BarPercentage = FMin(float(ExtHumanPawn(P).RepRegenHP) / float(P.HealthMax),1.f-BarPercentage);
2020-11-28 19:53:57 +00:00
Canvas.DrawColor = MakeColor(255,128,128,FadeAlpha);
2017-10-20 02:00:49 +00:00
Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength * BarPercentage, BarHeight, 0, 0, 32, 32);
}
}
2020-11-28 21:54:57 +00:00
2020-01-09 11:05:13 +00:00
simulated function DrawPerkIcons(KFPawn_Human KFPH, float PerkIconSize, float PerkIconPosX, float PerkIconPosY, float SupplyIconPosX, float SupplyIconPosY, bool bDropShadow)
{
local byte PrestigeLevel;
local ExtPlayerReplicationInfo KFPRI;
local color TempColor;
local float ResModifier;
KFPRI = ExtPlayerReplicationInfo(KFPH.PlayerReplicationInfo);
if (KFPRI == none)
{
return;
}
PrestigeLevel = KFPRI.GetActivePerkPrestigeLevel();
ResModifier = WorldInfo.static.GetResolutionBasedHUDScale() * FriendlyHudScale;
if (KFPRI.CurrentVoiceCommsRequest == VCT_NONE && KFPRI.ECurrentPerk != none && PrestigeLevel > 0)
{
Canvas.SetPos(PerkIconPosX, PerkIconPosY);
Canvas.DrawTile(KFPRI.ECurrentPerk.default.BasePerk.default.PrestigeIcons[PrestigeLevel - 1], PerkIconSize, PerkIconSize, 0, 0, 256, 256);
}
if (PrestigeLevel > 0)
{ //icon slot in image is not centered
Canvas.SetPos(PerkIconPosX + (PerkIconSize * (1 - PrestigeIconScale)) / 2, PerkIconPosY + PerkIconSize * 0.05f);
Canvas.DrawTile(KFPRI.GetCurrentIconToDisplay(), PerkIconSize * PrestigeIconScale, PerkIconSize * PrestigeIconScale, 0, 0, 256, 256);
}
else
{
Canvas.SetPos(PerkIconPosX, PerkIconPosY);
Canvas.DrawTile(KFPRI.GetCurrentIconToDisplay(), PerkIconSize, PerkIconSize, 0, 0, 256, 256);
}
if (KFPRI.PerkSupplyLevel > 0 && KFPRI.ECurrentPerk.default.BasePerk.static.GetInteractIcon() != none)
{
if (!bDropShadow)
{
if (KFPRI.PerkSupplyLevel == 2)
{
if (KFPRI.bPerkPrimarySupplyUsed && KFPRI.bPerkSecondarySupplyUsed)
{
TempColor = SupplierActiveColor;
}
else if (KFPRI.bPerkPrimarySupplyUsed || KFPRI.bPerkSecondarySupplyUsed)
{
TempColor = SupplierHalfUsableColor;
}
else
{
TempColor = SupplierUsableColor;
}
}
else if (KFPRI.PerkSupplyLevel == 1)
{
TempColor = KFPRI.bPerkPrimarySupplyUsed ? SupplierActiveColor : SupplierUsableColor;
}
Canvas.SetDrawColorStruct(TempColor);
}
Canvas.SetPos(SupplyIconPosX, SupplyIconPosY); //offset so that supplier icon shows up on the correct side of the player's health bar
Canvas.DrawTile(KFPRI.ECurrentPerk.default.BasePerk.static.GetInteractIcon(), (PlayerStatusIconSize * 0.75) * ResModifier, (PlayerStatusIconSize * 0.75) * ResModifier, 0, 0, 256, 256);
}
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
simulated function DrawMonsterHUD(KFPawn KFPH)
2017-10-20 02:00:49 +00:00
{
local float Percentage;
local float BarHeight, BarLength;
local vector ScreenPos, TargetLocation;
local Ext_T_MonsterPRI PRI;
local FontRenderInfo MyFontRenderInfo;
local float FontScale;
2020-11-28 19:53:57 +00:00
local byte FadeAlpha;
2017-10-20 02:00:49 +00:00
PRI = Ext_T_MonsterPRI(KFPH.PlayerReplicationInfo);
2020-11-28 20:12:58 +00:00
if (PRI==None)
2017-10-20 02:00:49 +00:00
return;
2020-11-28 19:53:57 +00:00
FadeAlpha = DrawToDistance(KFPH);
2020-11-28 20:04:55 +00:00
MyFontRenderInfo = Canvas.CreateFontRenderInfo(true);
2017-10-20 02:00:49 +00:00
BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale;
BarHeight = FMin(8.f * (float(Canvas.SizeX) / 1024.f), 8.f) * FriendlyHudScale;
TargetLocation = KFPH.Location + vect(0,0,1) * KFPH.GetCollisionHeight() * 0.8;
ScreenPos = Canvas.Project(TargetLocation);
2020-11-28 20:12:58 +00:00
if (ScreenPos.X < 0 || ScreenPos.X > Canvas.SizeX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.SizeY)
2017-10-20 02:00:49 +00:00
return;
//Draw health bar
Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax),1.f);
2020-01-09 11:05:13 +00:00
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor, FadeAlpha);
2017-10-20 02:00:49 +00:00
//Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
2020-01-09 11:05:13 +00:00
Canvas.DrawColor = PRI.OwnerPRI==PlayerOwner.PlayerReplicationInfo ? MakeColor(32,250,32,FadeAlpha) : MakeColor(250,32,32,FadeAlpha);
2017-10-20 02:00:49 +00:00
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 3);
2020-11-28 20:04:55 +00:00
Canvas.DrawText(PRI.PlayerName,,FontScale,FontScale, MyFontRenderInfo);
2017-10-20 02:00:49 +00:00
//draw HP icon
Canvas.SetPos(ScreenPos.X - (BarLength * 0.75), ScreenPos.Y - BarHeight * 2);
Canvas.DrawRect(PlayerStatusIconSize * FriendlyHudScale,PlayerStatusIconSize * FriendlyHudScale,HealthIconTex);
}
2020-11-28 21:54:57 +00:00
2017-10-20 02:00:49 +00:00
simulated function DrawPetInfo()
{
local float X,Y,Sc,XL,YL,YS;
local string S;
local int i;
X = Canvas.ClipX*0.165;
Y = Canvas.ClipY*0.925;
2017-10-20 02:00:49 +00:00
Canvas.Font = GUIStyle.PickFont(GUIStyle.DefaultFontSize,Sc);
Canvas.TextSize("ABC",XL,YS,Sc,Sc);
S = "Current Pet(s)";
2017-10-20 02:00:49 +00:00
Canvas.TextSize(S,XL,YL,Sc,Sc);
Y-=(YS*MyCurrentPet.Length);
Canvas.SetDrawColor(120,0,0,145);
2020-11-28 20:04:55 +00:00
GUIStyle.DrawRectBox(X, Y, BestPetXL * 1.04, YL, 4);
Canvas.DrawColor = MakeColor(255,255,255,255);
Canvas.SetPos(X,Y);
2017-10-20 02:00:49 +00:00
Canvas.DrawText(S,,Sc,Sc);
Canvas.SetDrawColor(8,8,8,145);
2020-11-28 20:04:55 +00:00
GUIStyle.DrawRectBox(X, Y + YS, BestPetXL * 1.04, YL * MyCurrentPet.Length, 4);
Canvas.DrawColor = MakeColor(32,250,32,255);
2020-11-28 20:12:58 +00:00
for (i=0; i<MyCurrentPet.Length; ++i)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
if (MyCurrentPet[i]==None)
2017-10-20 02:00:49 +00:00
{
MyCurrentPet.Remove(i--,1);
continue;
}
Y+=YS;
S = MyCurrentPet[i].MonsterName$" ("$MyCurrentPet[i].HealthStatus$"/"$MyCurrentPet[i].HealthMax$"HP)";
Canvas.TextSize(S,XL,YL,Sc,Sc);
Canvas.SetPos(X,Y);
2017-10-20 02:00:49 +00:00
Canvas.DrawText(S,,Sc,Sc);
2020-11-28 20:12:58 +00:00
if (XL > BestPetXL)
BestPetXL = XL;
2020-11-28 20:12:58 +00:00
if (YL > BestPetYL)
BestPetYL = YL;
2017-10-20 02:00:49 +00:00
}
}
2020-01-09 11:05:13 +00:00
function byte DrawToDistance(Actor A, optional float StartAlpha=255.f, optional float MinAlpha=90.f)
2017-10-20 02:00:49 +00:00
{
2020-11-28 19:53:57 +00:00
local float Dist, fZoom;
Dist = VSize(A.Location - PLCameraLoc);
2020-11-28 20:04:55 +00:00
if (Dist <= HealthBarFullVisDist || PlayerOwner.PlayerReplicationInfo.bOnlySpectator)
2020-11-28 19:53:57 +00:00
fZoom = 1.0;
else fZoom = FMax(1.0 - (Dist - HealthBarFullVisDist) / (HealthBarCutoffDist - HealthBarFullVisDist), 0.0);
return Clamp(StartAlpha * fZoom, MinAlpha, StartAlpha);
2017-10-20 02:00:49 +00:00
}
2020-11-28 20:04:55 +00:00
final function AddNumberMsg(int Amount, vector Pos, byte Type)
2017-10-20 02:00:49 +00:00
{
2020-11-28 19:53:57 +00:00
local Color C;
DamagePopups[NextDamagePopupIndex].Damage = Amount;
DamagePopups[NextDamagePopupIndex].HitTime = WorldInfo.TimeSeconds;
DamagePopups[NextDamagePopupIndex].Type = Type;
DamagePopups[NextDamagePopupIndex].HitLocation = Pos;
//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;
2020-11-28 20:04:55 +00:00
if (Type == 0 && Amount < 100) {
2020-11-28 19:53:57 +00:00
C.R = 220;
C.G = 0;
C.B = 0;
}
2020-11-28 20:04:55 +00:00
else if (Type == 1) {
2020-11-28 19:53:57 +00:00
C.R = 255;
C.G = 255;
C.B = 25;
}
2020-11-28 20:04:55 +00:00
else if (Type == 2) {
2020-11-28 19:53:57 +00:00
C.R = 32;
C.G = 240;
C.B = 32;
}
2020-11-28 20:04:55 +00:00
else if (Amount >= 300) {
2020-11-28 19:53:57 +00:00
C.R = 0;
C.G = 206;
C.B = 0;
}
2020-11-28 20:04:55 +00:00
else if (Amount >= 100) {
2020-11-28 19:53:57 +00:00
C.R = 206;
C.G = 206;
C.B = 0;
}
else {
C.R = 127;
C.G = 127;
C.B = 127;
}
DamagePopups[NextDamagePopupIndex].FontColor = C;
2020-11-28 20:12:58 +00:00
if (++NextDamagePopupIndex >= DAMAGEPOPUP_COUNT)
2020-11-28 19:53:57 +00:00
NextDamagePopupIndex=0;
}
2017-10-20 02:00:49 +00:00
final function DrawDamage()
{
2020-11-28 19:53:57 +00:00
local int i;
local float TimeSinceHit;
local vector CameraLocation, CamDir;
local rotator CameraRotation;
local vector HBScreenPos;
local float TextWidth, TextHeight, x, Sc;
local string S;
2017-10-20 02:00:49 +00:00
Canvas.Font = class'Engine'.Static.GetMediumFont();
Sc = 1;
KFPlayerController(Owner).GetPlayerViewPoint(CameraLocation, CameraRotation);
CamDir = vector(CameraRotation);
2020-11-28 20:12:58 +00:00
for (i=0; i < DAMAGEPOPUP_COUNT ; i++)
2017-10-20 02:00:49 +00:00
{
2020-11-28 19:53:57 +00:00
TimeSinceHit = WorldInfo.TimeSeconds - DamagePopups[i].HitTime;
2020-11-28 20:12:58 +00:00
if (TimeSinceHit > DamagePopupFadeOutTime
2020-11-28 20:04:55 +00:00
|| (Normal(DamagePopups[i].HitLocation - CameraLocation) dot Normal(CamDir) < 0.1)) //don't draw if player faced back to the hit location
2020-11-28 19:53:57 +00:00
continue;
2020-11-28 20:12:58 +00:00
switch (DamagePopups[i].Type)
2017-10-20 02:00:49 +00:00
{
case 0: // Pawn damage.
S = "-"$string(DamagePopups[i].Damage);
break;
case 1: // EXP.
S = "+"$string(DamagePopups[i].Damage)$" XP";
break;
case 2: // Health.
S = "+"$string(DamagePopups[i].Damage)$" HP";
break;
2017-10-20 02:00:49 +00:00
}
2020-11-28 19:53:57 +00:00
HBScreenPos = Canvas.Project(DamagePopups[i].HitLocation);
Canvas.TextSize(S,TextWidth,TextHeight,Sc,Sc);
2020-11-28 19:53:57 +00:00
//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
2020-11-28 20:04:55 +00:00
if (i % 2 == 0)
2020-11-28 19:53:57 +00:00
x *= -1.0;
HBScreenPos.X += x;
Canvas.DrawColor = DamagePopups[i].FontColor;
Canvas.DrawColor.A = 255 * Cos(0.5*Pi * TimeSinceHit/DamagePopupFadeOutTime);
2020-11-28 20:04:55 +00:00
Canvas.SetPos(HBScreenPos.X, HBScreenPos.Y);
Canvas.DrawText(S);
2020-11-28 19:53:57 +00:00
}
2017-10-20 02:00:49 +00:00
}
// Search for new inventory!
simulated function SearchInventoryForNewItem()
{
local int i,j;
2020-11-28 20:12:58 +00:00
if (WasNewlyAdded.Length!=OnlineSub.CurrentInventory.Length)
2017-10-20 02:00:49 +00:00
WasNewlyAdded.Length = OnlineSub.CurrentInventory.Length;
2020-11-28 20:12:58 +00:00
for (i=0; i<OnlineSub.CurrentInventory.Length; ++i)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
if (OnlineSub.CurrentInventory[i].NewlyAdded==1 && WasNewlyAdded[i]==0)
2017-10-20 02:00:49 +00:00
{
WasNewlyAdded[i] = 1;
2020-11-28 20:12:58 +00:00
if (WorldInfo.TimeSeconds<80.f || !bLoadedInitItems) // Skip initial inventory.
2017-10-20 02:00:49 +00:00
continue;
j = OnlineSub.ItemPropertiesList.Find('Definition', OnlineSub.CurrentInventory[i].Definition);
2020-11-28 20:12:58 +00:00
if (j != INDEX_NONE)
2017-10-20 02:00:49 +00:00
{
NewItems.Insert(0,1);
NewItems[0].Icon = Texture2D(DynamicLoadObject(OnlineSub.ItemPropertiesList[j].IconURL,Class'Texture2D'));
NewItems[0].Item = OnlineSub.ItemPropertiesList[j].Name$" ["$RarityStr(OnlineSub.ItemPropertiesList[j].Rarity)$"]";
NewItems[0].MsgTime = WorldInfo.TimeSeconds;
ExtPlayerController(Owner).ServerItemDropGet(NewItems[0].Item);
}
}
}
bLoadedInitItems = true;
}
2020-11-28 21:54:57 +00:00
2020-11-28 20:04:55 +00:00
simulated final function string RarityStr(byte R)
2017-10-20 02:00:49 +00:00
{
2020-11-28 20:12:58 +00:00
switch (R)
2017-10-20 02:00:49 +00:00
{
case ITR_Common: return "Common";
case ITR_Uncommon: return "Uncommon +";
case ITR_Rare: return "Rare ++";
case ITR_Legendary: return "Legendary +++";
case ITR_ExceedinglyRare: return "Exceedingly Rare ++++";
case ITR_Mythical: return "Mythical !!!!";
default: return "Unknown -";
}
}
simulated final function DrawItemsList()
{
local int i;
local float T,FontScale,XS,YS,YSize,XPos,YPos;
FontScale = Canvas.ClipY / 660.f;
Canvas.Font = GetFontSizeIndex(0);
Canvas.TextSize("ABC",XS,YSize,FontScale,FontScale);
YSize*=2.f;
YPos = Canvas.ClipY*0.82 - YSize;
XPos = Canvas.ClipX - YSize*0.15;
2020-11-28 20:12:58 +00:00
for (i=0; i<NewItems.Length; ++i)
2017-10-20 02:00:49 +00:00
{
T = WorldInfo.TimeSeconds-NewItems[i].MsgTime;
2020-11-28 20:12:58 +00:00
if (T>=10.f)
2017-10-20 02:00:49 +00:00
{
NewItems.Remove(i--,1);
continue;
}
2020-11-28 20:12:58 +00:00
if (T>9.f)
2017-10-20 02:00:49 +00:00
{
T = 255.f * (10.f-T);
Canvas.SetDrawColor(255,255,255,T);
}
else Canvas.SetDrawColor(255,255,255,255);
Canvas.TextSize(NewItems[i].Item,XS,YS,FontScale,FontScale);
2020-11-28 20:12:58 +00:00
/*if (NewItems[i].Icon!=None)
2017-10-20 02:00:49 +00:00
{
Canvas.SetPos(XPos-YSize,YPos);
Canvas.DrawRect(YSize,YSize,NewItems[i].Icon);
XS = XPos-(YSize*1.1)-XS;
}
2020-01-09 11:05:13 +00:00
else */XS = XPos-XS;
2017-10-20 02:00:49 +00:00
Canvas.SetPos(XS,YPos);
Canvas.DrawText("New Item:",,FontScale,FontScale);
Canvas.SetPos(XS,YPos+(YSize*0.5));
Canvas.DrawText(NewItems[i].Item,,FontScale,FontScale);
YPos-=YSize;
}
}
simulated function CheckForItems()
{
2020-11-28 20:12:58 +00:00
if (KFGameReplicationInfo(WorldInfo.GRI)!=none)
2017-10-20 02:00:49 +00:00
KFGameReplicationInfo(WorldInfo.GRI).ProcessChanceDrop();
SetTimer(260+FRand()*220.f,false,'CheckForItems');
}
defaultproperties
{
//DownArrowTex=Texture2D'UI_Widgets.MenuBarWidget_SWF_I10'
//MiddleTex=Texture2D'UI_Widgets.MenuBarWidget_SWF_I14'
//WaveBossTex=Texture2D'UI_HUD.InGameHUD_SWF_I35'
//WaveProgTex=Texture2D'UI_HUD.InGameHUD_SWF_IF5'
//TraderTimeTex=Texture2D'UI_HUD.InGameHUD_SWF_IF7'
//SyringeBarTex=Texture2D'UI_HUD.InGameHUD_SWF_I155'
//ArmorIconTex=Texture2D'UI_HUD.InGameHUD_SWF_I16A'
HealthIconTex=Texture2D'UI_Objective_Tex.UI_Obj_Healing_Loc'
//BatteryIconTex=Texture2D'UI_HUD.InGameHUD_SWF_I109'
BlackBGColor=(R=4,G=4,B=4,A=186)
RedBGColor=(R=164,G=32,B=32,A=186)
HUDTextColor=(R=250,G=250,B=250,A=186)
HUDClass=class'ExtMoviePlayer_HUD'
HealthBarFullVisDist=350
HealthBarCutoffDist=3500
DamagePopupFadeOutTime=3.000000
}