Prepare fixtures

This commit is contained in:
dkanus 2026-07-14 20:27:09 +07:00
commit 9c94356263
6021 changed files with 722805 additions and 22 deletions

View file

@ -0,0 +1,556 @@
Class ClientPerkRepLink extends LinkedReplicationInfo
DependsOn(SRHUDKillingFloor);
var int RDamageHealedStat, RWeldingPointsStat, RShotgunDamageStat, RHeadshotKillsStat, RChainsawKills,
RStalkerKillsStat, RBullpupDamageStat, RMeleeDamageStat, RFlameThrowerDamageStat,RTotalZedTimeStat,
RSelfHealsStat, RSoleSurvivorWavesStat, RCashDonatedStat, RFeedingKillsStat,RHuntingShotgunKills,
RBurningCrossbowKillsStat, RGibbedFleshpoundsStat, RStalkersKilledWithExplosivesStat,
RGibbedEnemiesStat, RBloatKillsStat, RSirenKillsStat, RKillsStat, RMedicKnifeKills, RExplosivesDamageStat,
TotalPlayTime, WinsCount, LostsCount;
var byte MinimumLevel,MaximumLevel;
var float NextRepTime,RequirementScaling;
var int ClientAccknowledged[2],SendIndex,ClientAckSkinNum;
struct FPerksListType
{
var class<SRVeterancyTypes> PerkClass;
var byte CurrentLevel;
};
var array<FPerksListType> CachePerks;
var SRStatsBase StatObject;
struct FShopItemIndex
{
var class<Pickup> PC;
var byte CatNum,bDLCLocked;
};
struct FShopCategoryIndex
{
var string Name;
var byte PerkIndex;
};
var array<FShopItemIndex> ShopInventory;
var array<Material> ShopPerkIcons;
var array<FShopCategoryIndex> ShopCategories;
var array<string> CustomChars;
var array<GUIBuyable> AllocatedObjects;
var array<SRHUDKillingFloor.SmileyMessageType> SmileyTags;
var int CurrentPerkProgress;
var KFPlayerReplicationInfo OwnerPRI;
var SRCustomProgress CustomLink;
var string ServerWebSite,UserID;
var bool bMinimalRequirements,bBWZEDTime,bNoStandardChars,bReceivedURL,bRepCompleted;
replication
{
reliable if( Role==ROLE_Authority && bNetOwner )
RDamageHealedStat, RWeldingPointsStat, RShotgunDamageStat, RHeadshotKillsStat, RChainsawKills,
RStalkerKillsStat, RBullpupDamageStat, RMeleeDamageStat, RFlameThrowerDamageStat,
RSelfHealsStat, RSoleSurvivorWavesStat, RCashDonatedStat, RFeedingKillsStat, RHuntingShotgunKills,
RBurningCrossbowKillsStat, RGibbedFleshpoundsStat, RStalkersKilledWithExplosivesStat, RExplosivesDamageStat,
RGibbedEnemiesStat, RBloatKillsStat, RTotalZedTimeStat, RSirenKillsStat, RKillsStat, RMedicKnifeKills,
TotalPlayTime, WinsCount, LostsCount, bBWZEDTime, bNoStandardChars,
MinimumLevel, RequirementScaling, MaximumLevel, bMinimalRequirements,CustomLink;
// Functions server can call.
reliable if( Role == ROLE_Authority )
ClientReceivePerk,ClientPerkLevel,ClientReceiveWeapon,ClientSendAcknowledge,ClientReceiveCategory,
ClientReceiveChar,ClientReceiveTag,ClientAllReceived,ClientReceiveURL;
reliable if( Role < ROLE_Authority )
ServerSelectPerk,ServerRequestPerks,ServerAcnowledge,ServerSetCharacter,ServerAckSkin;
}
function Destroyed()
{
local SRCustomProgress S,NS;
for( S=CustomLink; S!=None; S=NS )
{
NS = S.NextLink;
S.Destroy();
}
Super.Destroyed();
}
simulated final function string GetCustomValue( class<SRCustomProgress> C )
{
local SRCustomProgress S;
for( S=CustomLink; S!=None; S=S.NextLink )
if( S.Class.Name==C.Name )
return S.GetProgress();
return "";
}
simulated final function int GetCustomValueInt( class<SRCustomProgress> C )
{
local SRCustomProgress S;
for( S=CustomLink; S!=None; S=S.NextLink )
if( S.Class.Name==C.Name )
return S.GetProgressInt();
return 0;
}
final function SRCustomProgress AddCustomValue( class<SRCustomProgress> C )
{
local SRCustomProgress S,Last;
for( S=CustomLink; S!=None; S=S.NextLink )
{
Last = S;
if( S.Class.Name==C.Name )
return S;
}
S = Spawn(C,Owner);
S.RepLink = Self;
// Add new one in the end of the chain.
if( Last!=None )
Last.NextLink = S;
else CustomLink = S;
return S;
}
final function ProgressCustomValue( class<SRCustomProgress> C, int Count )
{
local SRCustomProgress S;
for( S=CustomLink; S!=None; S=S.NextLink )
{
if( S.Class.Name==C.Name )
{
S.IncrementProgress(Count);
break;
}
}
}
final function SpawnCustomLinks()
{
local int i;
for( i=0; i<CachePerks.Length; ++i )
CachePerks[i].PerkClass.Static.AddCustomStats(Self);
}
simulated static final function ClientPerkRepLink FindStats( PlayerController Other )
{
local LinkedReplicationInfo L;
local ClientPerkRepLink C;
if( Other.PlayerReplicationInfo==None )
{
foreach Other.DynamicActors(Class'ClientPerkRepLink',C)
if( C.Owner==Other )
{
C.RepLinkBroken();
return C;
}
return None; // Not yet init.
}
for( L=Other.PlayerReplicationInfo.CustomReplicationInfo; L!=None; L=L.NextReplicationInfo )
if( ClientPerkRepLink(L)!=None )
return ClientPerkRepLink(L);
if( Other.Level.NetMode!=NM_Client )
return None; // Not yet init.
foreach Other.DynamicActors(Class'ClientPerkRepLink',C)
if( C.Owner==Other )
{
C.RepLinkBroken();
return C;
}
return None;
}
simulated function Tick( float DeltaTime )
{
local PlayerController PC;
local LinkedReplicationInfo L;
if( Level.NetMode==NM_DedicatedServer )
{
Disable('Tick');
return;
}
PC = Level.GetLocalPlayerController();
if( Level.NetMode!=NM_Client && PC!=Owner )
{
Disable('Tick');
return;
}
if( PC.PlayerReplicationInfo==None )
return;
Disable('Tick');
Class'SRLevelCleanup'.Static.AddSafeCleanup(PC);
if( PC.PlayerReplicationInfo.CustomReplicationInfo!=None )
{
for( L=PC.PlayerReplicationInfo.CustomReplicationInfo; L!=None; L=L.NextReplicationInfo )
if( L==Self )
return; // Make sure not already added.
NextReplicationInfo = None;
for( L=PC.PlayerReplicationInfo.CustomReplicationInfo; L!=None; L=L.NextReplicationInfo )
if( L.NextReplicationInfo==None )
{
L.NextReplicationInfo = Self; // Add to the end of the chain.
return;
}
}
PC.PlayerReplicationInfo.CustomReplicationInfo = Self;
}
simulated final function RepLinkBroken() // Called by GUI when this is noticed.
{
Enable('Tick');
Tick(0);
}
final function Class<SRVeterancyTypes> PickRandomPerk()
{
local array< class<SRVeterancyTypes> > CA;
local int i;
for( i=0; i<CachePerks.Length; i++ )
{
if( CachePerks[i].PerkClass!=None && CachePerks[i].CurrentLevel>0 )
CA[CA.Length] = CachePerks[i].PerkClass;
}
if( CA.Length==0 )
return None;
return CA[Rand(CA.Length)];
}
final function ServerSelectPerk( Class<SRVeterancyTypes> VetType )
{
StatObject.ServerSelectPerk(VetType);
}
final function ServerRequestPerks()
{
if( NextRepTime<Level.TimeSeconds )
SendClientPerks();
}
final function SendClientPerks()
{
local byte i;
if( !StatObject.bStatsReadyNow )
return;
NextRepTime = Level.TimeSeconds+2.f;
for( i=0; i<CachePerks.Length; i++ )
ClientReceivePerk(i,CachePerks[i].PerkClass,CachePerks[i].CurrentLevel);
}
simulated function ClientReceivePerk( int Index, class<SRVeterancyTypes> V, byte Level )
{
// Setup correct icon for trader.
if( V.Default.PerkIndex<255 && V.Default.OnHUDIcon!=None )
{
if( ShopPerkIcons.Length<=V.Default.PerkIndex )
ShopPerkIcons.Length = V.Default.PerkIndex+1;
ShopPerkIcons[V.Default.PerkIndex] = V.Default.OnHUDIcon;
}
if( CachePerks.Length<=Index )
CachePerks.Length = (Index+1);
CachePerks[Index].PerkClass = V;
CachePerks[Index].CurrentLevel = Level;
}
simulated function ClientPerkLevel( int Index, byte CurLevel )
{
Level.GetLocalPlayerController().ReceiveLocalizedMessage(Class'KFVetEarnedMessageSR',(CurLevel-1),,,CachePerks[Index].PerkClass);
CachePerks[Index].CurrentLevel = CurLevel;
}
simulated function ClientReceiveWeapon( int Index, class<Pickup> P, byte Categ )
{
ShopInventory.Length = Max(ShopInventory.Length,Index+1);
if( ShopInventory[Index].PC==None )
{
ShopInventory[Index].PC = P;
ShopInventory[Index].CatNum = Categ;
if( class<KFWeapon>(P.Default.InventoryType)!=none
&& (class<KFWeapon>(P.Default.InventoryType).Default.AppID>0
|| class<KFWeapon>(P.Default.InventoryType).Default.UnlockedByAchievement!=-1) )
ShopInventory[Index].bDLCLocked = 1;
++ClientAccknowledged[0];
}
}
simulated function ClientReceiveCategory( byte Index, FShopCategoryIndex S )
{
ShopCategories.Length = Max(ShopCategories.Length,Index+1);
if( ShopCategories[Index].Name=="" )
{
ShopCategories[Index] = S;
++ClientAccknowledged[1];
}
}
simulated function ClientReceiveURL( string S, string ID )
{
ServerWebSite = S;
UserID = ID;
bReceivedURL = true;
}
simulated function ClientSendAcknowledge()
{
ServerAcnowledge(ClientAccknowledged[0],ClientAccknowledged[1]);
}
function ServerAcnowledge( int A, int B )
{
ClientAccknowledged[0] = A;
ClientAccknowledged[1] = B;
}
simulated function ClientReceiveChar( string CharName, int Num )
{
CustomChars.Length = Num+1;
CustomChars[Num] = CharName;
ServerAckSkin(Num+1);
}
simulated function ClientReceiveTag( Texture T, string Tag, bool bInCaps )
{
local int i;
i = SmileyTags.Length;
SmileyTags.Length = i+1;
SmileyTags[i].SmileyTex = T;
SmileyTags[i].SmileyTag = Tag;
SmileyTags[i].bInCAPS = bInCaps;
}
simulated function ClientAllReceived()
{
local PlayerController PC;
local int i;
bRepCompleted = true;
PC = Level.GetLocalPlayerController();
if( (PC!=None && PC==Owner) || Level.NetMode==NM_Client )
{
// Check if a DLC check is required.
for( i=(ShopInventory.Length-1); i>=0; --i )
if( ShopInventory[i].bDLCLocked!=0 )
{
Spawn(Class'SRSteamStatsGet',Owner).Link = Self;
break;
}
}
if( SmileyTags.Length==0 )
return;
if( PC!=None && SRHUDKillingFloor(PC.MyHUD)!=None )
SRHUDKillingFloor(PC.MyHUD).SmileyMsgs = SmileyTags;
}
function ServerAckSkin( int Index )
{
ClientAckSkinNum = Index;
}
simulated final function string PickRandomCustomChar()
{
local string S;
local int i;
if( CustomChars.Length==0 )
return "";
S = CustomChars[Rand(CustomChars.Length)];
i = InStr(S,":");
if( i>=0 )
S = Mid(S,i+1);
return S;
}
simulated final function bool IsCustomCharacter( string CN )
{
local int i;
for( i=0; i<CustomChars.Length; ++i )
if( CustomChars[i]~=CN || Right(CustomChars[i],Len(CN)+1)~=(":"$CN) )
return true;
return false;
}
simulated final function SelectedCharacter( string CN )
{
if( !IsCustomCharacter(CN) ) // Was not a custom character, update URL too.
{
if( bNoStandardChars && CustomChars.Length>0 ) // Denied.
return;
Level.GetLocalPlayerController().UpdateURL("Character", CN, True);
}
ServerSetCharacter(CN);
}
function ServerSetCharacter( string CN )
{
if( xPlayer(Owner)!=None )
StatObject.ChangeCharacter(CN);
}
final function bool CanBuyPickup( class<KFWeaponPickup> WC )
{
local int i;
local KFPlayerReplicationInfo K;
for( i=(ShopInventory.Length-1); i>=0; --i )
if( ShopInventory[i].PC==WC )
{
K = KFPlayerReplicationInfo(StatObject.PlayerOwner.PlayerReplicationInfo);
for( i=(CachePerks.Length-1); i>=0; --i )
if( !CachePerks[i].PerkClass.Static.AllowWeaponInTrader(WC,K,CachePerks[i].CurrentLevel) )
return false;
return true;
}
return false;
}
Auto state RepSetup
{
final function InitDLCCheck()
{
local int i;
for( i=(ShopInventory.Length-1); i>=0; --i )
{
if( class<KFWeapon>(ShopInventory[i].PC.Default.InventoryType)!=none
&& (class<KFWeapon>(ShopInventory[i].PC.Default.InventoryType).Default.AppID>0
|| class<KFWeapon>(ShopInventory[i].PC.Default.InventoryType).Default.UnlockedByAchievement!=-1) )
ShopInventory[i].bDLCLocked = 1;
}
}
Begin:
if( Level.NetMode==NM_Client )
Stop;
Sleep(1.f);
NetUpdateFrequency = 0.5f;
if( NetConnection(StatObject.PlayerOwner.Player)!=None ) // Network client.
{
ClientReceiveURL(ServerWebSite,StatObject.PlayerOwner.GetPlayerIDHash());
// Now MAKE SURE client receives the full inventory list.
while( ClientAccknowledged[0]<ShopInventory.Length || ClientAccknowledged[1]<ShopCategories.Length )
{
for( SendIndex=0; SendIndex<ShopInventory.Length; ++SendIndex )
{
ClientReceiveWeapon(SendIndex,ShopInventory[SendIndex].PC,ShopInventory[SendIndex].CatNum);
Sleep(0.1f);
}
for( SendIndex=0; SendIndex<ShopCategories.Length; ++SendIndex )
{
ClientReceiveCategory(SendIndex,ShopCategories[SendIndex]);
Sleep(0.1f);
}
ClientSendAcknowledge();
Sleep(1.f);
}
// Send client all the custom characters.
while( ClientAckSkinNum<CustomChars.Length )
{
ClientReceiveChar(CustomChars[ClientAckSkinNum],ClientAckSkinNum);
Sleep(0.15f);
}
// Send all chat icons.
for( SendIndex=0; SendIndex<SmileyTags.Length; ++SendIndex )
{
ClientReceiveTag(SmileyTags[SendIndex].SmileyTex,SmileyTags[SendIndex].SmileyTag,SmileyTags[SendIndex].bInCAPS);
Sleep(0.1f);
}
SmileyTags.Length = 0;
}
else
{
bReceivedURL = true;
InitDLCCheck();
}
ClientAllReceived();
GoToState('UpdatePerkProgress');
}
state UpdatePerkProgress
{
final function UpdateProgression()
{
local class<SRVeterancyTypes> SV;
local byte Lv;
local float V;
SV = Class<SRVeterancyTypes>(OwnerPRI.ClientVeteranSkill);
Lv = OwnerPRI.ClientVeteranSkillLevel+1;
if( Lv<MaximumLevel && SV!=None )
{
V = SV.Static.GetTotalProgress(Self,Lv) * 10000.f;
CurrentPerkProgress = V;
}
else CurrentPerkProgress = -1;
ForceValue();
}
final function ForceValue()
{
if( CurrentPerkProgress!=OwnerPRI.ThreeSecondScore )
{
OwnerPRI.ThreeSecondScore = CurrentPerkProgress;
OwnerPRI.NetUpdateTime = Level.TimeSeconds-1;
}
}
Begin:
Sleep(FRand());
OwnerPRI = KFPlayerReplicationInfo(StatObject.PlayerOwner.PlayerReplicationInfo);
if( OwnerPRI==None )
Stop;
while( true )
{
Sleep(0.5);
UpdateProgression();
Sleep(1);
ForceValue();
Sleep(1);
ForceValue();
Sleep(1);
ForceValue();
}
}
simulated final function ResetItem( GUIBuyable Item )
{
Item.ItemName = "";
Item.ItemDescription = "";
Item.ItemCategorie = "";
Item.ItemImage = None;
Item.ItemWeaponClass = None;
Item.ItemAmmoClass = None;
Item.ItemPickupClass = None;
Item.ItemCost = 0;
Item.ItemAmmoCost = 0;
Item.ItemFillAmmoCost = 0;
Item.ItemWeight = 0;
Item.ItemPower = 0;
Item.ItemRange = 0;
Item.ItemSpeed = 0;
Item.ItemAmmoCurrent = 0;
Item.ItemAmmoMax = 0;
Item.bSaleList = false;
Item.bSellable = false;
Item.bMelee = false;
Item.bIsVest = false;
Item.bIsFirstAidKit = false;
Item.ItemPerkIndex = 0;
Item.ItemSellValue = 0;
}
defaultproperties
{
MaximumLevel=7
RequirementScaling=1.000000
ShopPerkIcons(0)=Texture'KillingFloorHUD.Perks.Perk_Medic'
ShopPerkIcons(1)=Texture'KillingFloorHUD.Perks.Perk_Support'
ShopPerkIcons(2)=Texture'KillingFloorHUD.Perks.Perk_SharpShooter'
ShopPerkIcons(3)=Texture'KillingFloorHUD.Perks.Perk_Commando'
ShopPerkIcons(4)=Texture'KillingFloorHUD.Perks.Perk_Berserker'
ShopPerkIcons(5)=Texture'KillingFloorHUD.Perks.Perk_Firebug'
ShopPerkIcons(6)=Texture'KillingFloor2HUD.Perk_Icons.Perk_Demolition'
ShopPerkIcons(7)=Texture'KillingFloor2HUD.Perk_Icons.No_Perk_Icon'
UserID="Local"
bOnlyRelevantToOwner=True
bAlwaysRelevant=False
}

View file

@ -0,0 +1,61 @@
// Just a helper class to help manage dual wield weapons.
class DualWeaponsManager extends Object
abstract;
struct FDualList
{
var class<KFWeapon> Single,Dual;
};
var array<FDualList> DualMap;
static final function bool IsDualWeapon( class<Weapon> W, optional out class<KFWeapon> SingleType )
{
local int i;
if( W.Default.DemoReplacement!=None )
{
SingleType = class<KFWeapon>(W.Default.DemoReplacement);
return true;
}
for( i=(Default.DualMap.Length-1); i>=0; --i )
if( W==Default.DualMap[i].Dual )
{
SingleType = Default.DualMap[i].Single;
return true;
}
return false;
}
static final function bool HasDualies( class<Weapon> W, Inventory InvList, optional out class<KFWeapon> DualType )
{
local int i;
local Inventory In;
for ( In=InvList; In!=None; In=In.Inventory )
if( Weapon(In)!=None && Weapon(In).DemoReplacement==W )
{
DualType = class<KFWeapon>(In.Class);
return true;
}
for( i=(Default.DualMap.Length-1); i>=0; --i )
if( W==Default.DualMap[i].Single )
{
DualType = Default.DualMap[i].Dual;
W = Default.DualMap[i].Dual;
for ( In=InvList; In!=None; In=In.Inventory )
if( In.Class==W )
return true;
return false;
}
return false;
}
defaultproperties
{
DualMap(0)=(Single=Class'KFMod.Single',Dual=Class'KFMod.Dualies')
DualMap(1)=(Single=Class'KFMod.Magnum44Pistol',Dual=Class'KFMod.Dual44Magnum')
DualMap(2)=(Single=Class'KFMod.Deagle',Dual=Class'KFMod.DualDeagle')
DualMap(3)=(Single=Class'KFMod.FlareRevolver',Dual=Class'KFMod.DualFlareRevolver')
DualMap(4)=(Single=Class'KFMod.MK23Pistol',Dual=Class'KFMod.DualMK23Pistol')
}

View file

@ -0,0 +1,966 @@
//====================================================================
// HTML Text box, written by Marco
// Simply call SetContents to change window contents.
// Only callback available is for LaunchKFURL.
// ====================================================================
class GUIHTMLTextBox extends GUIMultiComponent;
struct FTextLine
{
var string Text,URL;
var color Color,ALColor;
var Font Font;
var byte Align,FontSize;
var int X,Y,XS,YS,Tab,TOffset;
var byte LineSkips;
var array<int> ImgList;
var bool bHasURL,bSplit;
};
var array<FTextLine> Lines;
struct FImageEntry
{
var Material Img;
var int X,Y,XS,YS,YOffset,XOffset;
var byte Align,Style;
};
var array<FImageEntry> Images;
var FImageEntry BgImage;
var float OldXSize,OldYSize;
var int YSize,HoverOverLinkLine,OldHoverLine;
var() Color BGColor;
var automated GUIScrollBarBase MyScrollBar;
var string TitleString;
var int CurTab;
var byte DefaultFontSize;
var bool bNeedsInit,bHasSplitLines,bNeedScrollbar;
function bool FocusFirst( GUIComponent Sender )
{
if ( MyScrollBar != None )
MyScrollBar.SetFocus(None);
else Super(GUIComponent).SetFocus(None);
return true;
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
MyScrollBar.bTabStop = false;
MyScrollBar.Refocus(Self);
}
final function int AddText( string Input, color TextColor, byte TextAlign, byte FontSize, out byte NumSkips )
{
local int i;
i = Lines.Length;
Lines.Length = i+1;
Lines[i].Text = Input;
Lines[i].Color = TextColor;
Lines[i].Align = TextAlign;
Lines[i].FontSize = FontSize;
Lines[i].LineSkips = NumSkips;
Lines[i].Tab = CurTab;
NumSkips = 0;
return i;
}
final function string ParseLinkType( string URL )
{
if( InStr(URL,"//")>0 )
return URL;
if( Left(URL,4)~="ftp." )
return "ftp://"$URL;
return "http://"$URL;
}
final function AddImage( string Input )
{
local string Temp;
local byte Align,Sty;
local Material M;
local int X,Y,XS,YS,i,j,z;
Align = 3;
Temp = GetOption(Input, "ALIGN=");
if (Temp != "")
{
switch( Caps(Temp) )
{
case "LEFT":
case "0":
Align = 0;
break;
case "CENTER":
case "1":
Align = 1;
break;
case "RIGHT":
case "2":
Align = 2;
break;
}
}
Temp = GetOption(Input, "STYLE=");
if (Temp != "")
{
switch( Caps(Temp) )
{
case "NORMAL":
case "0":
Sty = 0;
break;
case "STRETCH":
case "1":
Sty = 1;
break;
case "TILEDX":
case "2":
Sty = 2;
break;
case "TILEDY":
case "3":
Sty = 3;
break;
case "TILED":
case "4":
Sty = 4;
break;
}
}
Temp = GetOption(Input, "SRC=");
if (Temp != "")
M = Material(DynamicLoadObject(Temp,Class'Material'));
if( M==None )
M = Texture'DefaultTexture';
X = int(GetOption(Input, "VSPACE="));
Y = int(GetOption(Input, "HSPACE="));
XS = int(GetOption(Input, "WIDTH="));
YS = int(GetOption(Input, "HEIGHT="));
if( XS==0 )
XS = M.MaterialUSize();
if( YS==0 )
YS = M.MaterialVSize();
i = Images.Length;
Images.Length = i+1;
Images[i].Img = M;
Images[i].XOffset = X;
Images[i].YOffset = Y;
Images[i].XS = XS;
Images[i].YS = YS;
Images[i].Style = Sty;
Images[i].Align = Align;
j = Lines.Length-1;
z = Lines[j].ImgList.Length;
Lines[j].ImgList.Length = z+1;
Lines[j].ImgList[z] = i;
}
final function SetContents( string Input )
{
local string LeftText,HTML,RightText,Output,Temp,Link;
local int Index;
local color TextColor,LinkColor,ALinkColor,OrgTextColor;
local byte Alignment,FontScaler,NextLineSkips;
CurTab = 0;
BGColor.A = 0;
BgImage.Img = None;
Lines.Length = 0;
Images.Length = 0;
TitleString = "";
bHasSplitLines = false;
bNeedsInit = true;
// First remove new liners
Input = Repl(Input, Chr(13)$Chr(10), "");
Input = Repl(Input, Chr(13), "");
Input = Repl(Input, Chr(10), "");
Input = Repl(Input, Chr(9), " ");
Input = Repl(Input, "\\n", "<BR>");
TextColor = Class'HUD'.Default.WhiteColor;
OrgTextColor = Class'HUD'.Default.WhiteColor;
LinkColor = Class'HUD'.Default.BlueColor;
ALinkColor = Class'HUD'.Default.RedColor;
FontScaler = 3;
DefaultFontSize = 3;
Index = -1;
while (Input != "")
{
ParseHTML(Input, LeftText, HTML, RightText);
switch (GetTag(HTML))
{
// multiline HTML tags
case "P":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
NextLineSkips = 2;
Output = "";
}
else ++NextLineSkips;
break;
case "BR":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
NextLineSkips = 1;
Output = "";
}
else ++NextLineSkips;
break;
case "BODY":
Temp = GetOption(HTML, "BGCOLOR=");
if (Temp != "")
BGColor = ParseColor(Temp);
Temp = GetOption(HTML, "LINK=");
if (Temp != "")
LinkColor = ParseColor(Temp);
Temp = GetOption(HTML, "ALINK=");
if (Temp != "")
ALinkColor = ParseColor(Temp);
Temp = GetOption(HTML, "TEXT=");
if (Temp != "")
{
TextColor = ParseColor(Temp);
OrgTextColor = TextColor;
}
Temp = GetOption(HTML, "SIZE=");
if (Temp != "")
{
FontScaler = int(Temp);
DefaultFontSize = FontScaler;
}
Temp = GetOption(Input, "IMG=");
if (Temp != "")
{
if( BGColor.A==0 )
BGColor = Class'Hud'.Default.WhiteColor;
BgImage.Img = Material(DynamicLoadObject(Temp,Class'Material'));
if( BgImage.Img==None )
BgImage.Img = Texture'DefaultTexture';
BgImage.X = BgImage.Img.MaterialUSize();
BgImage.Y = BgImage.Img.MaterialVSize();
switch( Caps(GetOption(Input, "IMGSTYLE=")) )
{
case "TILED":
BgImage.XS = BgImage.X;
BgImage.YS = BgImage.Y;
BgImage.Style = 1;
Temp = GetOption(Input, "TILEX=");
if (Temp != "")
BgImage.XS = int(Temp);
Temp = GetOption(Input, "TILEY=");
if (Temp != "")
BgImage.YS = int(Temp);
break;
case "FITX":
BgImage.Style = 2;
break;
case "FITY":
BgImage.Style = 3;
break;
default: // FIT
BgImage.Style = 0;
}
BgImage.Align = 0;
if( GetOption(Input, "IMGLOCK=")=="0" )
BgImage.Align = 1;
}
Output $= LeftText;
break;
case "CENTER":
Output $= LeftText;
if ( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
NextLineSkips = Max(NextLineSkips,1);
Alignment = 1;
break;
case "RIGHT":
Output $= LeftText;
if ( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
NextLineSkips = Max(NextLineSkips,1);
Alignment = 2;
break;
case "/CENTER":
case "/RIGHT":
Index = AddText(Output $ LeftText,TextColor,Alignment,FontScaler,NextLineSkips);
++NextLineSkips;
Alignment = 0;
Output = "";
break;
// Inline HTML tags
case "H1":
Output $= LeftText;
if ( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
NextLineSkips = Max(NextLineSkips,1);
FontScaler = 5;
Alignment = 1;
break;
case "/H1":
Index = AddText(Output $ LeftText,TextColor,Alignment,FontScaler,NextLineSkips);
++NextLineSkips;
Output = "";
FontScaler = DefaultFontSize;
Alignment = 0;
break;
case "FONT":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
Temp = GetOption(HTML, "COLOR=");
if (Temp != "")
TextColor = ParseColor(Temp);
Temp = GetOption(HTML, "SIZE=");
if (Temp != "")
FontScaler = int(Temp);
break;
case "/FONT":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
TextColor = OrgTextColor;
FontScaler = DefaultFontSize;
break;
case "TAB":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
CurTab = int(GetOption(HTML, "X="));
break;
case "/TAB":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
CurTab = 0;
break;
case "TITLE":
Output $= LeftText;
break;
case "/TITLE":
TitleString = LeftText;
break;
case "A":
Output $= LeftText;
if( Output!="" )
{
Index = AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
}
Link = GetOption(HTML, "HREF=");
break;
case "/A":
Output $= LeftText;
Index = AddText(Output,LinkColor,Alignment,FontScaler,NextLineSkips);
Lines[Index].ALColor = ALinkColor;
Lines[Index].bHasURL = true;
if( Link=="" )
Lines[Index].URL = ParseLinkType(Output);
else Lines[Index].URL = ParseLinkType(Link);
Output = "";
FontScaler = DefaultFontSize;
Alignment = 0;
break;
case "IMG":
Output $= LeftText;
if( Output!="" || NextLineSkips>0 )
AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
Output = "";
AddImage(HTML);
break;
default:
Output = Output $ LeftText;
break;
}
Input = RightText;
}
AddText(Output,TextColor,Alignment,FontScaler,NextLineSkips);
}
// Get the next HTML tag, the text before it and everthing after it.
final function ParseHTML(string Input, out string LeftText, out string HTML, out string RightText)
{
local int i;
i = InStr(Input, "<");
if (i == -1)
{
LeftText = Input;
HTML = "";
RightText = "";
return;
}
LeftText = Left(Input, i);
HTML = Mid(Input, i);
i = InStr(HTML, ">");
if (i == -1)
{
RightText = "";
return;
}
RightText = Mid(HTML, i+1);
HTML = Left(HTML, i+1);
}
final function string GetTag(string HTML)
{
local int i;
if (HTML == "")
return "";
HTML = Mid(HTML, 1); // lose <
i = FirstMatching(InStr(HTML, ">"), InStr(HTML, " "));
if (i == -1)
return Caps(HTML);
else
return Caps(Left(HTML, i));
}
final function string GetOption(string HTML, string Option)
{
local int i, j;
local string s;
i = InStr(Caps(HTML), Caps(Option));
if (i == 1 || Mid(HTML, i-1, 1) == " ")
{
s = Mid(HTML, i+Len(Option));
j = FirstMatching(InStr(s, ">"), InStr(s, " "));
s = Left(s, j);
if (Left(s, 1) == "\"")
s = Mid(s, 1);
if (Right(s, 1) == "\"")
s = Left(s, Len(s) - 1);
return s;
}
return "";
}
final function int FirstMatching(int i, int j)
{
if (i == -1)
return j;
if (j == -1)
return i;
return Min(i, j);
}
final function Color ParseColor(string S)
{
local Color C;
local int i;
S = Caps(S);
if (Left(S, 1) == "#")
{
C.R = (GetHexDigit(Mid(S, 1, 1)) << 4) + GetHexDigit(Mid(S, 2, 1));
C.G = (GetHexDigit(Mid(S, 3, 1)) << 4) + GetHexDigit(Mid(S, 4, 1));
C.B = (GetHexDigit(Mid(S, 5, 1)) << 4) + GetHexDigit(Mid(S, 6, 1));
}
else if (Left(S, 4) == "RGB(")
{
S = Mid(S, 4);
i = InStr(S,",");
C.R = int(Left(S,i));
S = Mid(S,i+1);
i = InStr(S,",");
C.G = int(Left(S,i));
C.B = int(Mid(S,i+1));
}
else
{
switch( S )
{
case "RED":
C.R = 255;
C.G = 0;
C.B = 0;
break;
case "BLUE":
C.R = 0;
C.G = 0;
C.B = 255;
break;
case "GREEN":
C.R = 0;
C.G = 255;
C.B = 0;
break;
case "YELLOW":
C.R = 255;
C.G = 255;
C.B = 0;
break;
case "BLACK":
C.R = 0;
C.G = 0;
C.B = 0;
break;
default: // WHITE
C.R = 255;
C.G = 255;
C.B = 255;
}
}
C.A = 255;
return C;
}
final function byte GetHexDigit(string D)
{
local byte i;
i = Asc(D);
if( i>=48 && i<=57 ) // i>='0' && i<='9'
return (i-48); // i-'0'
return Min(i-55,15); // i-('A'-10)
}
function ResolutionChanged( int ResX, int ResY )
{
bNeedsInit = true;
}
final function SplitLine( int iLine, int iOffset )
{
local int i;
local string S;
++iLine;
Lines.Insert(iLine,1);
S = Lines[iLine-1].Text;
for( i=iOffset; i<Len(S); ++i )
if( Mid(S,i,1)!=" " )
break;
Lines[iLine].Text = Mid(S,i);
Lines[iLine-1].Text = Left(S,iOffset);
Lines[iLine].URL = Lines[iLine-1].URL;
Lines[iLine].Color = Lines[iLine-1].Color;
Lines[iLine].ALColor = Lines[iLine-1].ALColor;
Lines[iLine].Align = Lines[iLine-1].Align;
Lines[iLine].FontSize = Lines[iLine-1].FontSize;
Lines[iLine].Tab = Lines[iLine-1].Tab;
Lines[iLine].LineSkips = 1;
Lines[iLine].bHasURL = Lines[iLine-1].bHasURL;
Lines[iLine].bSplit = true;
bHasSplitLines = true;
}
final protected function InitHTMLArea( Canvas C )
{
local float XS,YS;
local int i,j,X,Y,iStart,BestHeight,FontSize,PrevY,Remain,iLastWord,iLen,z,ImgHeight;
// Used to detect resolution changes when text needs realignment.
OldXSize = ActualWidth(WinWidth);
OldYSize = ActualHeight(WinHeight);
// Merge splitted lines again
if( bHasSplitLines )
{
bHasSplitLines = false;
for( i=1; i<Lines.Length; ++i )
{
if( Lines[i].bSplit )
{
Lines[i-1].Text @= Lines[i].Text;
Lines.Remove(i--,1);
}
}
}
// Setup background image scaling
if( BgImage.Img!=None )
{
switch( BgImage.Style )
{
case 1: // Tiled
if( BgImage.X==BgImage.XS )
BgImage.XOffset = C.ClipX;
else
{
XS = C.ClipX / float(BgImage.XS) * float(BgImage.X);
BgImage.XOffset = XS;
}
if( BgImage.Y==BgImage.YS )
BgImage.YOffset = C.ClipY;
else
{
XS = C.ClipY / float(BgImage.YS) * float(BgImage.Y);
BgImage.YOffset = XS;
}
break;
case 2: // Fit X
XS = C.ClipY * (C.ClipX / float(BgImage.X));
Log(XS);
BgImage.YS = XS;
break;
case 3: // Fit Y
XS = C.ClipX * (C.ClipY / float(BgImage.Y));
Log(XS);
BgImage.XS = XS;
break;
}
}
FontSize = -2;
if ( C.SizeY < 480 )
FontSize++;
if ( C.SizeY < 600 )
FontSize++;
if ( C.SizeY < 800 )
FontSize++;
if ( C.SizeY < 1024 )
FontSize++;
if ( C.SizeY < 1250 )
FontSize++;
C.SetPos(0,0);
if( Lines.Length>0 )
{
while( true )
{
if( i>=Lines.Length || (i>0 && Lines[i].LineSkips>0) )
{
for( j=iStart; j<i; ++j )
{
switch( Lines[j].Align )
{
case 0: // Left
Lines[j].X = Lines[j].TOffset;
break;
case 1: // Center
Lines[j].X = (C.ClipX-X+Lines[j].TOffset)/2;
break;
case 2: // Right
Lines[j].X = C.ClipX-X+Lines[j].TOffset;
break;
}
}
if( i>=Lines.Length )
break;
X = 0;
iStart = i;
PrevY = BestHeight;
BestHeight = 0;
}
if( Lines[i].FontSize>=247 )
Lines[i].Font = Class'HUDKillingFloor'.Static.LoadFontStatic(Lines[i].FontSize-247);
else Lines[i].Font = Class'HUDKillingFloor'.Static.LoadFontStatic(Clamp(8-(FontSize+Lines[i].FontSize),0,8));
C.Font = Lines[i].Font;
if( Lines[i].Text=="" )
{
C.TextSize("ABC",XS,YS);
XS = 0;
}
else C.TextSize(Lines[i].Text,XS,YS);
if( Lines[i].LineSkips>0 )
{
if( PrevY==0 )
PrevY = YS;
Y+=(PrevY*Lines[i].LineSkips);
}
X = Max(X,Lines[i].Tab);
Lines[i].TOffset = X;
Lines[i].Y = Y;
Lines[i].YS = YS;
BestHeight = Max(BestHeight,YS);
if( (X+XS)>C.ClipX )
{
// Split to next row.
Remain = C.ClipX-X;
iLastWord = 0;
iLen = Len(Lines[i].Text);
for( j=1; j<iLen; ++j )
{
C.TextSize(Left(Lines[i].Text,j),XS,YS);
if( Remain<XS )
{
if( iLastWord==0 ) // Must cut off a word now.
SplitLine(i,Max(j-1,0));
else SplitLine(i,iLastWord);
break;
}
if( Mid(Lines[i].Text,j,1)==" " )
iLastWord = j+1;
}
C.TextSize(Lines[i].Text,XS,YS);
}
Lines[i].XS = XS;
X+=XS;
for( j=0; j<Lines[i].ImgList.Length; ++j )
{
z = Lines[i].ImgList[j];
if( Images[z].Align==3 )
Images[z].X = X+Images[z].XOffset;
else Images[z].X = Images[z].XOffset;
Images[z].Y = Y+Images[z].YOffset;
ImgHeight = Max(ImgHeight,Images[z].Y+Images[z].YS);
}
++i;
}
YSize = Max(Y+BestHeight,ImgHeight);
}
else YSize = 0;
bNeedScrollbar = (YSize>C.ClipY);
if( bNeedScrollbar )
{
MyScrollBar.EnableMe();
MyScrollBar.Step = 16;
MyScrollBar.BigStep = 512;
MyScrollBar.ItemCount = YSize;
MyScrollBar.ItemsPerPage = C.ClipY;
MyScrollBar.UpdateGripPosition(0);
}
else MyScrollBar.DisableMe();
}
simulated final function DrawTileStretchedClipped( Canvas C, Material M, float XS, float YS )
{
C.CurX += C.OrgX;
C.CurY += C.OrgY;
if( C.CurX<C.OrgX )
{
XS-=(C.OrgX-C.CurX);
C.CurX = C.OrgX;
}
if( C.CurY<C.OrgY )
{
YS-=(C.OrgY-C.CurY);
C.CurY = C.OrgY;
}
if( (C.CurX+XS)>C.ClipX )
XS = (C.ClipX-C.CurX);
if( (C.CurY+YS)>C.ClipY )
YS = (C.ClipY-C.CurY);
C.DrawTileStretched(M,XS,YS);
}
function bool RenderHTMLText( canvas C )
{
local float CX,CY,YS;
local int i,YOffset,MX,MY;
local bool bMouseOnClient;
CX = C.ClipX;
CY = C.ClipY;
C.OrgX = ActualLeft(WinLeft);
C.OrgY = ActualTop(WinTop);
C.ClipX = ActualWidth(WinWidth)-MyScrollBar.ActualWidth(MyScrollBar.WinWidth);
C.ClipY = ActualHeight(WinHeight);
if( bNeedsInit || OldXSize!=ActualWidth(WinWidth) || OldYSize!=ActualHeight(WinHeight) )
{
bNeedsInit = false;
InitHTMLArea(C);
}
if( bNeedScrollbar )
YOffset = MyScrollBar.CurPos;
C.Style = 5; // STY_Alpha
if( BGColor.A>0 )
{
C.SetPos(0,0);
C.DrawColor = BGColor;
if( BgImage.Img!=None )
{
if( BgImage.Align==1 ) // not locked on screen.
MX = YOffset;
switch( BgImage.Style )
{
case 0: // Stretched to fit
C.DrawTileClipped(BgImage.Img,C.ClipX,C.ClipY,0,MX,BgImage.X,BgImage.Y);
break;
case 1: // Tiled
C.DrawTileClipped(BgImage.Img,C.ClipX,C.ClipY,0,MX,BgImage.XOffset,BgImage.YOffset);
break;
case 2: // Fit X
C.DrawTileClipped(BgImage.Img,C.ClipX,C.ClipY,0,MX,BgImage.X,BgImage.YS);
break;
case 3: // Fit Y
C.DrawTileClipped(BgImage.Img,C.ClipX,C.ClipY,0,MX,BgImage.XS,BgImage.Y);
break;
}
}
else C.DrawTile(Texture'WhiteTexture',C.ClipX,C.ClipY,0,0,1,1);
}
MX = Controller.MouseX-C.OrgX;
MY = Controller.MouseY-C.OrgY;
bMouseOnClient = (MX>=0 && MX<=C.ClipX && MY>=0 && MY<=C.ClipY);
HoverOverLinkLine = -1;
MY+=YOffset;
C.DrawColor = Class'HUD'.Default.WhiteColor;
for( i=0; i<Images.Length; ++i )
{
C.CurY = Images[i].Y-YOffset;
if( (C.CurY+Images[i].YS)<0 || C.CurY>C.ClipY )
continue;
switch( Images[i].Align )
{
case 0: // Left
case 3: // Unaligned, postition after text.
C.CurX = 0;
break;
case 1: // Center
C.CurX = (C.ClipX-Images[i].XS)/2;
break;
case 1: // Right
C.CurX = C.ClipX-Images[i].XS;
break;
}
C.CurX += Images[i].X;
switch( Images[i].Style )
{
case 1: // Stretched
DrawTileStretchedClipped(C,Images[i].Img,Images[i].XS,Images[i].YS);
break;
case 2: // Tiled on X axis
C.DrawTileClipped(Images[i].Img,Images[i].XS,Images[i].YS,0,0,Images[i].XS,Images[i].Img.MaterialVSize());
break;
case 3: // Tiled on Y axis
C.DrawTileClipped(Images[i].Img,Images[i].XS,Images[i].YS,0,0,Images[i].Img.MaterialUSize(),Images[i].YS);
break;
case 4: // Fully tiled
C.DrawTileClipped(Images[i].Img,Images[i].XS,Images[i].YS,0,0,Images[i].XS,Images[i].YS);
break;
default: // Normal
C.DrawTileClipped(Images[i].Img,Images[i].XS,Images[i].YS,0,0,Images[i].Img.MaterialUSize(),Images[i].Img.MaterialVSize());
}
}
for( i=0; i<Lines.Length; ++i )
{
C.SetPos(Lines[i].X,Lines[i].Y-YOffset);
if( (C.CurY+Lines[i].YS)<0 || Lines[i].Text=="" )
continue;
if( C.CurY>C.ClipY )
break;
// Check if mouse hovers over URL
if( bMouseOnClient && Lines[i].bHasURL && MX>=Lines[i].X && MX<=(Lines[i].X+Lines[i].XS)
&& MY>=Lines[i].Y && MY<=(Lines[i].Y+Lines[i].YS) )
{
HoverOverLinkLine = i;
bMouseOnClient = false; // No need to check on rest anymore.
C.DrawColor = Lines[i].ALColor;
}
else C.DrawColor = Lines[i].Color;
C.Font = Lines[i].Font;
C.DrawTextClipped(Lines[i].Text);
if( Lines[i].bHasURL )
{
YS = Max(Lines[i].YS/15,1);
C.SetPos(Lines[i].X,Lines[i].Y+Lines[i].YS-(YS*2)-YOffset);
if( C.CurY<C.ClipY )
C.DrawTileClipped(Texture'WhiteTexture',Lines[i].XS,YS,0,0,1,1);
}
}
if( OldHoverLine!=HoverOverLinkLine )
{
OldHoverLine = HoverOverLinkLine;
if( HoverOverLinkLine>=0 )
{
Controller.PlayInterfaceSound(CS_Hover);
SetToolTipText(Lines[HoverOverLinkLine].URL);
}
else SetToolTipText("");
}
C.OrgX = 0;
C.OrgY = 0;
C.ClipX = CX;
C.ClipY = CY;
return false;
}
function bool LaunchURL(GUIComponent Sender)
{
if( HoverOverLinkLine>=0 )
{
if( Left(Lines[HoverOverLinkLine].URL,8)~="kfurl://" )
LaunchKFURL(Mid(Lines[HoverOverLinkLine].URL,8));
else if( Left(Lines[HoverOverLinkLine].URL,5)~="kf://" )
ChangeGameURL(Mid(Lines[HoverOverLinkLine].URL,5));
else LaunchURLPage(Lines[HoverOverLinkLine].URL);
}
return true;
}
delegate LaunchKFURL( string URL );
delegate ChangeGameURL( string URL )
{
Class'SRLevelCleanup'.Static.AddSafeCleanup(PlayerOwner(),URL);
}
delegate LaunchURLPage( string URL )
{
PlayerOwner().Player.Console.DelayedConsoleCommand("START "$URL);
}
defaultproperties
{
Begin Object Class=GUIVertScrollBar Name=TheScrollbar
WinLeft=0.970000
WinWidth=0.030000
WinHeight=1.000000
bBoundToParent=True
bScaleToParent=True
OnPreDraw=TheScrollbar.GripPreDraw
End Object
MyScrollBar=GUIVertScrollBar'ServerPerks.GUIHTMLTextBox.TheScrollbar'
bNeedsInit=True
PropagateVisibility=True
StyleName="NoBackground"
bAcceptsInput=True
Begin Object Class=GUIToolTip Name=GUIListBoxBaseToolTip
ExpirationSeconds=0.000000
End Object
ToolTip=GUIToolTip'ServerPerks.GUIHTMLTextBox.GUIListBoxBaseToolTip'
OnDraw=GUIHTMLTextBox.RenderHTMLText
OnClick=GUIHTMLTextBox.LaunchURL
}

View file

@ -0,0 +1,420 @@
class KFPCServ extends KFPlayerController_Story;
var transient vector CamPos;
var transient rotator CamRot;
var transient Actor CamActor;
var bool bUseAdvBehindview;
replication
{
reliable if( Role==ROLE_Authority )
bUseAdvBehindview;
}
simulated function UpdateHintManagement(bool bUseHints)
{
if( KF_StoryGRI(Level.GRI)!=None )
Super.UpdateHintManagement(bUseHints);
else Super(KFPlayerController).UpdateHintManagement(bUseHints);
}
exec function ThrowWeapon()
{
if( KF_StoryGRI(Level.GRI)!=None )
Super.ThrowWeapon();
else Super(KFPlayerController).ThrowWeapon();
}
function rotator AdjustAim(FireProperties FiredAmmunition, vector projStart, int aimerror)
{
local Actor Other;
local float TraceRange;
local vector HitLocation,HitNormal;
if( Pawn==None || !bBehindview || !bUseAdvBehindview || Vehicle(Pawn)!=None )
return Super.AdjustAim(FiredAmmunition,projStart,aimerror);
if ( FiredAmmunition.bInstantHit )
TraceRange = 10000.f;
else TraceRange = 4000.f;
PlayerCalcView(CamActor,CamPos,CamRot);
foreach Pawn.TraceActors(Class'Actor',Other,HitLocation,HitNormal,CamPos+TraceRange*vector(CamRot),CamPos)
{
if( Other!=Pawn && (Other==Level || Other.bBlockActors || Other.bProjTarget || Other.bWorldGeometry)
&& KFPawn(Other)==None && KFBulletWhipAttachment(Other)==None )
break;
}
if( FiredAmmunition.bInstantHit && Other!=None )
InstantWarnTarget(Other,FiredAmmunition,vector(Rotation));
if( Other!=None )
return rotator(HitLocation-projStart);
return Rotation;
}
simulated function rotator GetViewRotation()
{
if( (bBehindView && !bUseAdvBehindview && Pawn!=None) || (bBehindView && Vehicle(Pawn)!=None) )
return Pawn.Rotation;
return Rotation;
}
simulated final function bool GetShoulderCam( out vector Pos, Pawn Other )
{
local vector HL,HN;
if( Vehicle(Other)!=None )
return false;
Pos = Other.Location + Other.EyePosition();
CamPos = vect(-40,20,10) >> Rotation;
if( Pawn.Trace(HL,HN,Pos+Normal(CamPos)*(VSize(CamPos)+10.f),Pos,false)!=None )
Pos = Pos+Normal(CamPos)*(VSize(HL-Pos)-10.f);
else Pos += CamPos;
return true;
}
event PlayerCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation )
{
local Pawn PTarget;
if( Base!=None )
SetBase(None); // This error may happen on client, causing major desync.
if ( LastPlayerCalcView == Level.TimeSeconds && CalcViewActor != None && CalcViewActor.Location == CalcViewActorLocation )
{
ViewActor = CalcViewActor;
CameraLocation = CalcViewLocation;
CameraRotation = CalcViewRotation;
return;
}
// If desired, call the pawn's own special callview
if( Pawn != None && Pawn.bSpecialCalcView && (ViewTarget == Pawn) )
{
// try the 'special' calcview. This may return false if its not applicable, and we do the usual.
if ( Pawn.SpecialCalcView(ViewActor, CameraLocation, CameraRotation) )
{
CacheCalcView(ViewActor,CameraLocation,CameraRotation);
return;
}
}
if ( (ViewTarget == None) || ViewTarget.bDeleteMe )
{
if ( (Pawn != None) && !Pawn.bDeleteMe )
SetViewTarget(Pawn);
else if ( RealViewTarget != None )
SetViewTarget(RealViewTarget);
else
SetViewTarget(self);
}
ViewActor = ViewTarget;
CameraLocation = ViewTarget.Location;
if ( ViewTarget == Pawn )
{
if( bBehindView ) // up and behind
{
if( !bUseAdvBehindview || !GetShoulderCam(CameraLocation,Pawn) )
CalcBehindView(CameraLocation, CameraRotation, CameraDist * Pawn.Default.CollisionRadius);
else CameraRotation = Rotation;
}
else CalcFirstPersonView( CameraLocation, CameraRotation );
CacheCalcView(ViewActor,CameraLocation,CameraRotation);
return;
}
if ( ViewTarget == self )
{
CameraRotation = Rotation;
CacheCalcView(ViewActor,CameraLocation,CameraRotation);
return;
}
if ( ViewTarget.IsA('Projectile') )
{
if ( Projectile(ViewTarget).bSpecialCalcView && Projectile(ViewTarget).SpecialCalcView(ViewActor, CameraLocation, CameraRotation, bBehindView) )
{
CacheCalcView(ViewActor,CameraLocation,CameraRotation);
return;
}
if ( !bBehindView )
{
CameraLocation += (ViewTarget.CollisionHeight) * vect(0,0,1);
CameraRotation = Rotation;
CacheCalcView(ViewActor,CameraLocation,CameraRotation);
return;
}
}
CameraRotation = ViewTarget.Rotation;
PTarget = Pawn(ViewTarget);
if ( PTarget != None )
{
if ( (Level.NetMode == NM_Client) || (bDemoOwner && (Level.NetMode != NM_Standalone)) )
{
PTarget.SetViewRotation(TargetViewRotation);
CameraRotation = BlendedTargetViewRotation;
PTarget.EyeHeight = TargetEyeHeight;
}
else if ( PTarget.IsPlayerPawn() )
CameraRotation = PTarget.GetViewRotation();
if (PTarget.bSpecialCalcView && PTarget.SpectatorSpecialCalcView(self, ViewActor, CameraLocation, CameraRotation))
{
CacheCalcView(ViewActor, CameraLocation, CameraRotation);
return;
}
if ( !bBehindView )
CameraLocation += PTarget.EyePosition();
}
if ( bBehindView )
{
CameraLocation = CameraLocation + (ViewTarget.Default.CollisionHeight - ViewTarget.CollisionHeight) * vect(0,0,1);
CalcBehindView(CameraLocation, CameraRotation, CameraDist * ViewTarget.Default.CollisionRadius);
}
CacheCalcView(ViewActor,CameraLocation,CameraRotation);
}
exec function ChangeCharacter(string newCharacter, optional string inClass)
{
local ClientPerkRepLink S;
S = Class'ClientPerkRepLink'.Static.FindStats(Self);
if( S!=None )
S.SelectedCharacter(newCharacter);
else Super.ChangeCharacter(newCharacter,inClass);
}
function SetPawnClass(string inClass, string inCharacter)
{
if( SRStatsBase(SteamStatsAndAchievements)!=none )
SRStatsBase(SteamStatsAndAchievements).ChangeCharacter(inCharacter);
else
{
PawnSetupRecord = class'xUtil'.static.FindPlayerRecord(inCharacter);
PlayerReplicationInfo.SetCharacterName(inCharacter);
}
}
function SendSelectedVeterancyToServer(optional bool bForceChange)
{
if( Level.NetMode!=NM_Client && SRStatsBase(SteamStatsAndAchievements)!=none )
SRStatsBase(SteamStatsAndAchievements).WaveEnded();
}
function SelectVeterancy(class<KFVeterancyTypes> VetSkill, optional bool bForceChange)
{
if( SRStatsBase(SteamStatsAndAchievements)!=none )
SRStatsBase(SteamStatsAndAchievements).ServerSelectPerk(Class<SRVeterancyTypes>(VetSkill));
}
// Allow clients fix the behindview bug themself
exec function BehindView( Bool B )
{
if ( Vehicle(Pawn)==None || Vehicle(Pawn).bAllowViewChange ) // Allow vehicles to limit view changes
{
ClientSetBehindView(B);
bBehindView = B;
}
}
exec function ToggleBehindView()
{
ServerToggleBehindview();
}
function ServerToggleBehindview()
{
local bool B;
if( Vehicle(Pawn)==None || Vehicle(Pawn).bAllowViewChange )
{
B = !bBehindView;
ClientSetBehindView(B);
bBehindView = B;
}
}
function ShowBuyMenu(string wlTag,float maxweight)
{
StopForceFeedback();
ClientOpenMenu(string(Class'SRGUIBuyMenu'),,wlTag,string(maxweight));
}
// Fix for vehicle mod crashes.
simulated function postfxon(int i)
{
if( Viewport(Player)!=None )
Super.postfxon(i);
}
simulated function postfxoff(int i)
{
if( Viewport(Player)!=None )
Super.postfxoff(i);
}
simulated function postfxblur(float f)
{
if( Viewport(Player)!=None )
Super.postfxblur(f);
}
simulated function postfxbw(float f, optional bool bDoNotTurnOffFadeFromBlackEffect)
{
if( Viewport(Player)!=None )
Super.postfxbw(f,bDoNotTurnOffFadeFromBlackEffect);
}
// Hide weapon highlight when using this shortcut key.
exec function SwitchWeapon(byte F)
{
local Weapon W;
if ( Pawn!=None )
{
W = Pawn.PendingWeapon;
Pawn.SwitchWeapon(F);
if( W!=Pawn.PendingWeapon && HudKillingFloor(MyHUD)!=None )
{
HudKillingFloor(MyHUD).SelectedInventory = Pawn.PendingWeapon;
HudKillingFloor(MyHUD).HideInventory();
}
}
}
// Poosh's preloading code fix.===================================
simulated function PreloadFireModeAssets(class<WeaponFire> WF)
{
local class<Projectile> P;
if ( WF == none || WF == Class'KFMod.NoFire' )
return;
if ( class<KFFire>(WF) != none && class<KFFire>(WF).default.FireSoundRef != "" )
class<KFFire>(WF).static.PreloadAssets(Level);
else if ( class<KFMeleeFire>(WF) != none && class<KFMeleeFire>(WF).default.FireSoundRef != "" )
class<KFMeleeFire>(WF).static.PreloadAssets();
else if ( class<KFShotgunFire>(WF) != none && class<KFShotgunFire>(WF).default.FireSoundRef != "" )
class<KFShotgunFire>(WF).static.PreloadAssets(Level);
// preload projectile assets
P = WF.default.ProjectileClass;
//log("Projectile =" @ P, default.class.outer.name);
if ( P == none )
return;
if ( class<CrossbuzzsawBlade>(P) != none )
class<CrossbuzzsawBlade>(P).static.PreloadAssets();
else if ( class<LAWProj>(P) != none && class<LAWProj>(P).default.StaticMeshRef != "" )
class<LAWProj>(P).static.PreloadAssets();
else if ( class<M79GrenadeProjectile>(P) != none && class<M79GrenadeProjectile>(P).default.StaticMeshRef != "" )
class<M79GrenadeProjectile>(P).static.PreloadAssets();
else if ( class<SPGrenadeProjectile>(P) != none && class<SPGrenadeProjectile>(P).default.StaticMeshRef != "" )
class<SPGrenadeProjectile>(P).static.PreloadAssets();
else if ( class<HealingProjectile>(P) != none && class<HealingProjectile>(P).default.StaticMeshRef != "" )
class<HealingProjectile>(P).static.PreloadAssets();
else if ( class<CrossbowArrow>(P) != none && class<CrossbowArrow>(P).default.MeshRef != "" )
class<CrossbowArrow>(P).static.PreloadAssets();
else if ( class<M99Bullet>(P) != none )
class<M99Bullet>(P).static.PreloadAssets();
else if ( class<PipeBombProjectile>(P) != none && class<PipeBombProjectile>(P).default.StaticMeshRef != "" )
class<PipeBombProjectile>(P).static.PreloadAssets();
// More DLC
else if ( class<SealSquealProjectile>(P) != none && class<SealSquealProjectile>(P).default.StaticMeshRef != "" )
class<SealSquealProjectile>(P).static.PreloadAssets();
}
simulated final function UnloadFireModeAssets(class<WeaponFire> WF)
{
local class<Projectile> P;
if ( WF==none || WF==Class'KFMod.NoFire' )
return;
if ( class<KFFire>(WF) != none && class<KFFire>(WF).default.FireSoundRef != "" )
class<KFFire>(WF).static.UnloadAssets();
else if ( class<KFMeleeFire>(WF) != none && class<KFMeleeFire>(WF).default.FireSoundRef != "" )
class<KFMeleeFire>(WF).static.UnloadAssets();
else if ( class<KFShotgunFire>(WF) != none && class<KFShotgunFire>(WF).default.FireSoundRef != "" )
class<KFShotgunFire>(WF).static.UnloadAssets();
// Unload projectile assets only if refs aren't empty (i.e. they have been dynamically loaded)
P = WF.default.ProjectileClass;
if ( P == none || P.default.StaticMesh != none )
return;
if ( class<CrossbuzzsawBlade>(P) != none )
class<CrossbuzzsawBlade>(P).static.UnloadAssets();
else if ( class<LAWProj>(P) != none && class<LAWProj>(P).default.StaticMeshRef != "" )
class<LAWProj>(P).static.UnloadAssets();
else if ( class<M79GrenadeProjectile>(P) != none && class<M79GrenadeProjectile>(P).default.StaticMeshRef != "" )
class<M79GrenadeProjectile>(P).static.UnloadAssets();
else if ( class<SPGrenadeProjectile>(P) != none && class<SPGrenadeProjectile>(P).default.StaticMeshRef != "" )
class<SPGrenadeProjectile>(P).static.UnloadAssets();
else if ( class<HealingProjectile>(P) != none && class<HealingProjectile>(P).default.StaticMeshRef != "" )
class<HealingProjectile>(P).static.UnloadAssets();
else if ( class<CrossbowArrow>(P) != none && class<CrossbowArrow>(P).default.MeshRef != "" )
class<CrossbowArrow>(P).static.UnloadAssets();
else if ( class<M99Bullet>(P) != none )
class<M99Bullet>(P).static.UnloadAssets();
else if ( class<PipeBombProjectile>(P) != none && class<PipeBombProjectile>(P).default.StaticMeshRef != "" )
class<PipeBombProjectile>(P).static.UnloadAssets();
// More DLC
else if ( class<SealSquealProjectile>(P) != none && class<SealSquealProjectile>(P).default.StaticMeshRef != "" )
class<SealSquealProjectile>(P).static.UnloadAssets();
}
simulated function ClientWeaponSpawned(class<Weapon> WClass, Inventory Inv)
{
local class<KFWeapon> W;
local class<KFWeaponAttachment> Att;
// log("ScrnPlayerController.ClientWeaponSpawned()" @ WClass $ ". Default Mesh = " $ WClass.default.Mesh, default.class.outer.name);
// super.ClientWeaponSpawned(WClass, Inv);
W = class<KFWeapon>(WClass);
// preload assets only for weapons that have no static ones
// damned Tripwire's code doesn't bother for cheking is there ref set or not!
if ( W != none)
{
// preload weapon assets
if ( W.default.Mesh == none )
W.static.PreloadAssets(Inv);
Att = class<KFWeaponAttachment>(W.default.AttachmentClass);
// 2013/01/22 EDIT: bug fix
if ( Att != none && Att.default.Mesh == none )
{
if ( Inv != none )
Att.static.PreloadAssets(KFWeaponAttachment(Inv.ThirdPersonActor));
else
Att.static.PreloadAssets();
}
PreloadFireModeAssets(W.default.FireModeClass[0]);
PreloadFireModeAssets(W.default.FireModeClass[1]);
}
}
simulated function ClientWeaponDestroyed(class<Weapon> WClass)
{
local class<KFWeapon> W;
local class<KFWeaponAttachment> Att;
// log(default.class @ "ClientWeaponDestroyed()" @ WClass, default.class.outer.name);
// super.ClientWeaponDestroyed(WClass);
W = class<KFWeapon>(WClass);
// if default mesh is set, then count that weapon has static assets, so don't unload them
// that's lame, but not so lame as Tripwire's original code
if ( W != none && W.default.MeshRef != "" && W.static.UnloadAssets() )
{
Att = class<KFWeaponAttachment>(W.default.AttachmentClass);
if ( Att != none && Att.default.Mesh == none )
Att.static.UnloadAssets();
UnloadFireModeAssets(W.default.FireModeClass[0]);
UnloadFireModeAssets(W.default.FireModeClass[1]);
}
}
defaultproperties
{
LobbyMenuClassString="ServerPerks.SRLobbyMenu"
PawnClass=Class'ServerPerks.SRHumanPawn'
}

View file

@ -0,0 +1,30 @@
class KFVetEarnedMessagePL extends CriticalEventPlus
abstract;
var(Message) localized string EarnedString;
static function string GetString(
optional int Switch,
optional PlayerReplicationInfo RelatedPRI_1,
optional PlayerReplicationInfo RelatedPRI_2,
optional Object OptionalObject
)
{
local string S;
if( Class<KFVeterancyTypes>(OptionalObject)==None )
return "";
S = Default.EarnedString;
ReplaceText(S,"%s",Eval(RelatedPRI_1!=None,RelatedPRI_1.PlayerName,"Someone"));
ReplaceText(S,"%v",Class<KFVeterancyTypes>(OptionalObject).Default.VeterancyName);
ReplaceText(S,"%l",string(Switch));
Return S;
}
defaultproperties
{
EarnedString="%s has earned %v level %l!"
Lifetime=6
DrawColor=(G=50,R=255)
PosY=0.100000
}

View file

@ -0,0 +1,89 @@
class KFVetEarnedMessageSR extends CriticalEventPlus
abstract;
var(Message) localized string EarnedString;
static function RenderComplexMessage(
Canvas Canvas,
out float XL,
out float YL,
optional String MessageString,
optional int Switch,
optional PlayerReplicationInfo RelatedPRI_1,
optional PlayerReplicationInfo RelatedPRI_2,
optional Object OptionalObject
)
{
local float XS,YS,XPos,YPos,IconSize;
local Material M1,M2;
local byte A;
XPos = Canvas.CurX;
YPos = Canvas.CurY;
Canvas.DrawTextClipped(MessageString);
if( Class<SRVeterancyTypes>(OptionalObject)!=None )
{
A = Canvas.DrawColor.A;
Class<SRVeterancyTypes>(OptionalObject).Static.PreDrawPerk(Canvas,Switch,M1,M2);
Canvas.DrawColor.A = A;
if( M1!=None )
{
Canvas.TextSize(MessageString,XS,YS);
IconSize = FMin(YS*2.5f,256.f);
YPos-=(IconSize-YS)*0.5f;
Canvas.SetPos(XPos-(IconSize*1.1f),YPos);
A = Canvas.Style;
Canvas.Style = ERenderStyle.STY_Alpha;
Canvas.DrawTile( M1, IconSize, IconSize, 0, 0, M1.MaterialUSize(), M1.MaterialVSize() );
Canvas.SetPos(XPos+XS+(IconSize*0.1f),YPos);
Canvas.DrawTile( M1, IconSize, IconSize, 0, 0, M1.MaterialUSize(), M1.MaterialVSize() );
Canvas.Style = A;
}
}
}
static function string GetString(
optional int Switch,
optional PlayerReplicationInfo RelatedPRI_1,
optional PlayerReplicationInfo RelatedPRI_2,
optional Object OptionalObject
)
{
local string S;
if( Class<KFVeterancyTypes>(OptionalObject)==None )
return "";
S = Default.EarnedString;
ReplaceText(S,"%v",Class<KFVeterancyTypes>(OptionalObject).Default.VeterancyName);
ReplaceText(S,"%l",string(Switch));
Return S;
}
static function ClientReceive(
PlayerController P,
optional int Switch,
optional PlayerReplicationInfo RelatedPRI_1,
optional PlayerReplicationInfo RelatedPRI_2,
optional Object OptionalObject
)
{
P.ClientPlaySound(Sound'KF_InterfaceSnd.Perks.PerkAchieved',true,2.f,SLOT_Talk);
P.ClientPlaySound(Sound'KF_InterfaceSnd.Perks.PerkAchieved',true,2.f,SLOT_Interface);
if( SRHUDKillingFloor(P.myHUD)!=None && KFPlayerReplicationInfo(P.PlayerReplicationInfo)!=None
&& OptionalObject!=None && KFPlayerReplicationInfo(P.PlayerReplicationInfo).ClientVeteranSkill==OptionalObject )
{
// Temporarly fill the bar.
SRHUDKillingFloor(P.myHUD).LevelProgressBar = 1.f;
SRHUDKillingFloor(P.myHUD).NextLevelTimer = P.Level.TimeSeconds+1.f;
}
Super.ClientReceive(P,Switch,RelatedPRI_1,RelatedPRI_2,OptionalObject);
}
defaultproperties
{
EarnedString="You have qualified for %v level %l!"
bComplexString=True
Lifetime=8
DrawColor=(B=50,G=50,R=255)
PosY=0.300000
FontSize=3
}

View file

@ -0,0 +1,142 @@
class SRBufferedTCPLink extends BufferedTCPLink;
var IpAddr ServerIpAddr;
var string ReceiveState;
var string ErrorName;
var string RemoteAddress,RemoteURL;
var int RemotePort,ContentLength;
var bool bHasError,bHasData,bReceivedHeader;
final function OnError( string E )
{
bHasError = true; // set error flag
ErrorName = E;
SetTimer(0,false);
}
final function StartBuffering( string URL )
{
local int i;
Disable('Tick');
ResetBuffer();
i = InStr(URL,"/");
if( i>0 )
{
RemoteAddress = Left(URL,i);
RemoteURL = Mid(URL,i);
}
else
{
RemoteAddress = URL;
RemoteURL = "/index.html";
}
i = InStr(RemoteAddress,":");
if( i==-1 )
RemotePort = 80; // connect to http port
else
{
RemotePort = int(Mid(RemoteAddress,i+1));
RemoteAddress = Left(RemoteAddress,i);
}
Resolve(RemoteAddress);
}
function ResolveFailed()
{
OnError("Resolve failure ("$RemoteAddress$")");
}
function Resolved( IpAddr Addr )
{
// Set the address
ServerIpAddr.Addr = Addr.Addr;
ServerIpAddr.Port = RemotePort;
// Bind the local port.
if( BindPort() == 0 )
OnError("Port couldn't be bound");
else
{
OpenNoSteam( ServerIpAddr );
SetTimer(6,false);
}
}
function Opened()
{
local string S;
S = "GET "$RemoteURL$" HTTP/1.1"$CRLF$"Host: "$RemoteAddress$CRLF$"UserID: "$
Class'ClientPerkRepLink'.Static.FindStats(Level.GetLocalPlayerController()).UserID$CRLF$CRLF$CRLF;
SendText(S);
SetTimer(20,false); // 20 sec timeout
}
final function ParseHeader( out string S )
{
local int i;
i = InStr(S,"Content-Length: ");
if( i==-1 )
{
OnError("Received invalid HTML header:|"$S);
return;
}
S = Mid(S,i+16);
i = InStr(S,CRLF);
if( i==-1 )
{
ContentLength = int(S);
S = "";
}
else
{
ContentLength = int(Left(S,i));
S = Mid(S,i+1);
i = InStr(S,CRLF$CRLF);
if( i==-1 )
S = "";
else S = Mid(S,i+Len(CRLF$CRLF));
}
}
function ReceivedText(string Text)
{
if( !bReceivedHeader )
{
bReceivedHeader = true;
ParseHeader(Text);
}
InputBuffer $= Text;
ContentLength-=Len(Text);
if( ContentLength<=0 )
{
SetTimer(0,false);
bHasData = true;
}
}
function DestroyLink()
{
SetTimer(0.0,False);
if(IsConnected())
Close();
LifeSpan = 5;
}
function Timer()
{
OnError("Connection timed out.");
}
function Closed()
{
SetTimer(0.0,False);
if( InputBuffer!="" )
bHasData = true;
else if( !bHasError )
OnError("Connection closed without data received.");
}
defaultproperties
{
}

View file

@ -0,0 +1,276 @@
//=============================================================================
// Buy Menu Filter for the trader
//=============================================================================
// Killing Floor Source
// Copyright (C) 2013 Tripwire Interactive LLC
// Jeff "Captain Mallard" Robinson
//=============================================================================
class SRBuyMenuFilter extends KFBuyMenuFilter;
var SRBuyMenuSaleList SaleListBox;
var array<KFIndexedGUIImage> SmallButtons;
var array<GUIImage> ButtonBGImg;
var() Texture NonSelectedBack;
var int OldPerkIndex,OldGroupIndex;
var bool bHasInit;
event InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super(GUIMultiComponent).InitComponent(MyController, MyOwner);
if( !bHasInit )
UpdatePerkIcons();
}
event Opened(GUIComponent Sender)
{
super(GUIMultiComponent).Opened( Sender );
if( !bHasInit )
UpdatePerkIcons();
}
final function KFIndexedGUIImage AddButton( int Index )
{
local KFIndexedGUIImage S;
local GUIImage B;
if( SmallButtons.Length==9 ) // Can't add more or menu will look ugly.
return None;
S = KFIndexedGUIImage(AddComponent(string(Class'KFIndexedGUIImage')));
S.WinWidth = 0.04;
S.WinHeight = 0.04;
S.WinLeft = 0.98;
S.WinTop = 0.052;
S.ImageStyle = ISTY_Scaled;
S.Renderweight = 0.6;
S.OnClick = InternalOnClick;
S.Index = Index;
S.bBoundToParent = true;
SmallButtons[SmallButtons.Length] = S;
B = GUIImage(AddComponent(string(Class'GUIImage')));
B.WinWidth = 0.04;
B.WinHeight = 0.04;
B.WinLeft = 0.98;
B.WinTop = 0.05;
B.Image = NonSelectedBack;
B.ImageStyle = ISTY_Scaled;
B.Renderweight = 0.5;
B.bBoundToParent = true;
ButtonBGImg[ButtonBGImg.Length] = B;
return S;
}
final function UpdatePerkIcons()
{
local ClientPerkRepLink CPRL;
local int i,j,Index;
local KFIndexedGUIImage S;
CPRL = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if( CPRL==None || !CPRL.bRepCompleted )
return;
bHasInit = true;
AddButton(-1); // Add favorites button.
for( i=0; i<CPRL.ShopCategories.Length; ++i )
{
Index = CPRL.ShopCategories[i].PerkIndex;
if( Index<CPRL.ShopPerkIcons.Length )
{
for( j=(SmallButtons.Length-1); j>=0; --j )
if( SmallButtons[j].Index==Index )
break;
if( j>=0 )
continue; // Already added.
S = AddButton(Index);
if( S==None )
continue;
for( j=(CPRL.CachePerks.Length-1); j>=0; --j )
if( Index==CPRL.CachePerks[j].PerkClass.Default.PerkIndex )
{
S.Hint = CPRL.CachePerks[j].PerkClass.Default.VeterancyName;
S.Image = CPRL.CachePerks[j].PerkClass.Default.OnHUDIcon;
break;
}
if( j==-1 )
{
S.Hint = Class'KFBuyMenuFilter'.Default.PerkSelectIcon7.Hint;
S.Image = NoPerkIcon;
}
}
}
// Name em approprietly.
SmallButtons[0].Hint = Class'KFBuyMenuFilter'.Default.PerkSelectIcon8.Hint;
SmallButtons[0].Image = FavoritesIcon;
bResized = false;
}
final function int GroupToPerkIndex( int In )
{
return Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner()).ShopCategories[In].PerkIndex;
}
function bool MyOnDraw(Canvas C)
{
local int i,CurIndex,CurGroup;
local KFPlayerReplicationInfo KFPRI;
if( !bHasInit )
{
UpdatePerkIcons();
if( !bHasInit )
return false;
}
// make em square
if ( !bResized )
{
ResizeIcons(C);
RealignIcons();
}
KFPRI = KFPlayerReplicationInfo(PlayerOwner().PlayerReplicationInfo);
CurIndex = -2;
if( KFPRI!=None && KFPRI.ClientVeteranSkill!=None )
CurIndex = KFPRI.ClientVeteranSkill.Default.PerkIndex;
CurGroup = SaleListBox.ActiveCategory;
if( OldPerkIndex!=CurIndex || OldGroupIndex!=CurGroup )
{
OldPerkIndex = CurIndex;
OldGroupIndex = CurGroup;
if( CurGroup>=0 )
CurGroup = GroupToPerkIndex(CurGroup);
// Draw the available perks
for( i=0; i<SmallButtons.Length; ++i )
{
// Check if current perk player uses now.
if( SmallButtons[i].Index==CurIndex )
SmallButtons[i].ImageColor.A = 255;
else SmallButtons[i].ImageColor.A = 95;
// Check if corresponding group index is open on buy menu.
if( SmallButtons[i].Index==CurGroup )
ButtonBGImg[i].Image = CurPerkBack;
else ButtonBGImg[i].Image = NonSelectedBack;
}
}
return false;
}
final function int GetNextCategory( int Index )
{
local ClientPerkRepLink C;
local int i,First;
local bool bFoundCurrent;
C = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
First = -1;
for( i=0; i<C.ShopCategories.Length; ++i )
{
if( Index==C.ShopCategories[i].PerkIndex )
{
if( First==-1 )
First = i;
if( OldGroupIndex==i )
bFoundCurrent = true;
else if( bFoundCurrent )
return i;
}
}
return First;
}
function bool InternalOnClick(GUIComponent Sender)
{
local int Index;
if ( Sender.IsA('KFIndexedGUIImage') )
{
Index = KFIndexedGUIImage(Sender).Index;
if( Index>=0 )
Index = GetNextCategory(Index);
SaleListBox.SetCategoryNum(Index,true);
}
return false;
}
function ResizeIcons(Canvas C)
{
local float sizeX, sizeY;
local int i;
sizeX = (C.ClipY / C.ClipX) * BoxSizeX;
sizeY = (C.ClipY / C.ClipX) * BoxSizeY;
for( i=0; i<SmallButtons.Length; ++i )
{
ButtonBGImg[i].WinWidth = sizeX;
SmallButtons[i].WinWidth = sizeY;
}
bResized = true;
}
function RealignIcons()
{
local int i;
local float IconWidth, TotalWidth, WidthLeft, WidthLeftForEachIcon, IconPadding;
IconWidth = SmallButtons[0].WinWidth;
TotalWidth = IconWidth * SmallButtons.Length;
WidthLeft = 1.f - TotalWidth;
WidthLeftForEachIcon = WidthLeft / SmallButtons.Length;
IconPadding = WidthLeftForEachIcon / 2.f;
for( i = 0; i <SmallButtons.Length; ++i ) // size of PerkSelectIcons
{
SmallButtons[i].WinLeft = IconPadding + (IconPadding + IconWidth + IconPadding) * i;
ButtonBGImg[i].WinLeft = IconPadding + (IconPadding + IconWidth + IconPadding) * i;
}
}
defaultproperties
{
NonSelectedBack=Texture'KF_InterfaceArt_tex.Menu.Perk_box_unselected'
OldPerkIndex=9999
OldGroupIndex=9999
PerkBack0=None
PerkBack1=None
PerkBack2=None
PerkBack3=None
PerkBack4=None
PerkBack5=None
PerkBack6=None
PerkBack7=None
PerkBack8=None
PerkSelectIcon0=None
PerkSelectIcon1=None
PerkSelectIcon2=None
PerkSelectIcon3=None
PerkSelectIcon4=None
PerkSelectIcon5=None
PerkSelectIcon6=None
PerkSelectIcon7=None
PerkSelectIcon8=None
}

View file

@ -0,0 +1,544 @@
//=============================================================================
// The trader menu's list with items for sale
//=============================================================================
class SRBuyMenuSaleList extends KFBuyMenuSaleList;
#exec obj load file="KF_InterfaceArt_tex.utx"
var int ActiveCategory,SelectionOffset;
var localized string WeaponGroupText;
var string FavoriteGroupName;
var() Material CategoryTex,CategoryPerkTex,SelectedCatPerkTex,CategoryArrow,CategoryArrowSel;
var array<Material> ListPerkIcons;
event Opened(GUIComponent Sender)
{
super(GUIVertList).Opened(Sender);
// Get localized string
FavoriteGroupName = Class'KFBuyMenuFilter'.Default.PerkSelectIcon8.Hint;
// Fixed script warnings.
UpdateForSaleBuyables();
}
final function GUIBuyable GetSelectedBuyable()
{
if( Index<0 || Index>=CanBuys.Length || CanBuys[Index]>1 || (Index-SelectionOffset)<0 || (Index-SelectionOffset)>=ForSaleBuyables.Length )
return None;
return ForSaleBuyables[Index-SelectionOffset];
}
final function CopyAllBuyables()
{
local ClientPerkRepLink L;
local int i;
L = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if( L==None )
return;
for( i=0; i<ForSaleBuyables.Length; ++i )
if( ForSaleBuyables[i]!=None )
L.AllocatedObjects[L.AllocatedObjects.Length] = ForSaleBuyables[i];
}
final function GUIBuyable AllocateEntry( ClientPerkRepLink L )
{
local GUIBuyable G;
if( L.AllocatedObjects.Length==0 )
return new Class'GUIBuyable';
G = L.AllocatedObjects[0];
L.ResetItem(G);
L.AllocatedObjects.Remove(0,1);
return G;
}
final function SetCategoryNum( int N, optional bool bScrollTo )
{
if( ActiveCategory==N )
ActiveCategory = -2;
else ActiveCategory = N;
SelectionOffset = (N+2);
UpdateForSaleBuyables();
Index = N+1;
if( bScrollTo )
SetTopItem(Index);
}
event Closed(GUIComponent Sender, bool bCancelled)
{
CopyAllBuyables();
ForSaleBuyables.Length = 0;
super.Closed(Sender, bCancelled);
}
final function bool DualIsInInventory( Class<Weapon> WC )
{
local Inventory I;
for( I=PlayerOwner().Pawn.Inventory; I!=None; I=I.Inventory )
{
if( Weapon(I)!=None && Weapon(I).DemoReplacement==WC )
return true;
}
return false;
}
final function bool IsInInventoryWep( Class<Weapon> WC )
{
local Inventory I;
for( I=PlayerOwner().Pawn.Inventory; I!=None; I=I.Inventory )
if( I.Class==WC )
return true;
return false;
}
final function bool CheckGoldGunAvailable( class<KFWeaponPickup> WC )
{
local int i;
local Inventory Inv;
local class<KFWeaponPickup> WPC;
for( Inv=PlayerOwner().Pawn.Inventory; Inv!=None; Inv=Inv.Inventory )
{
if( KFWeapon(Inv)==None || Inv.PickupClass==None )
continue;
WPC = class<KFWeaponPickup>(Inv.PickupClass);
if( WPC!=None && WPC.Default.VariantClasses.Length>0 )
{
for( i=(WC.Default.VariantClasses.Length-1); i>=0; --i )
{
if( WC.Default.VariantClasses[i]==Inv.PickupClass )
return true;
}
for( i=(WPC.Default.VariantClasses.Length-1); i>=0; --i )
{
if( WPC.Default.VariantClasses[i]==WC )
return true;
}
}
}
return false;
}
final function KFShopVolume_Story GetCurrentShop()
{
local KFPlayerController_Story StoryPC;
StoryPC = KFPlayerController_Story(PlayerOwner());
if(StoryPC != none)
return StoryPC.CurrentShopVolume;
return none;
}
function FilterBuyablesList();
function int PopulateBuyables()
{
return 0;
}
function UpdateForSaleBuyables()
{
local class<KFVeterancyTypes> PlayerVeterancy;
local KFPlayerReplicationInfo KFPRI;
local ClientPerkRepLink CPRL;
local GUIBuyable ForSaleBuyable;
local class<KFWeaponPickup> ForSalePickup;
local int j, DualDivider, i, Num, z, PerkSaleOffset;
local class<KFWeapon> ForSaleWeapon,SecType;
local class<SRVeterancyTypes> Blocker;
local KFShopVolume_Story CurrentShop;
local byte DLCLocked;
// Clear the ForSaleBuyables array
CopyAllBuyables();
ForSaleBuyables.Length = 0;
// Grab the items for sale
CPRL = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if( CPRL==None )
return; // Hmmmm?
KFPRI = KFPlayerReplicationInfo(PlayerOwner().PlayerReplicationInfo);
// Grab Players Veterancy for quick reference
if ( KFPRI!=none )
PlayerVeterancy = KFPRI.ClientVeteranSkill;
if( PlayerVeterancy==None )
PlayerVeterancy = class'KFVeterancyTypes';
CurrentShop = GetCurrentShop();
// Grab the weapons!
if( ActiveCategory>=-1 )
{
if( CurrentShop!=None )
Num = CurrentShop.SaleItems.Length;
else Num = CPRL.ShopInventory.Length;
for ( z=0; z<Num; z++ )
{
if( CurrentShop!=None )
{
// Allow story mode volume limit weapon availability.
ForSalePickup = class<KFWeaponPickup>(CurrentShop.SaleItems[z]);
if( ForSalePickup==None )
continue;
for ( j=(CPRL.ShopInventory.Length-1); j>=CPRL.ShopInventory.Length; --j )
if( CPRL.ShopInventory[j].PC==ForSalePickup )
break;
if( j<0 )
continue;
}
else
{
ForSalePickup = class<KFWeaponPickup>(CPRL.ShopInventory[z].PC);
j = z;
}
if ( ForSalePickup==None || class<KFWeapon>(ForSalePickup.default.InventoryType)==None || class<KFWeapon>(ForSalePickup.default.InventoryType).default.bKFNeverThrow
|| IsInInventory(ForSalePickup) )
continue;
if( ActiveCategory==-1 )
{
if( !Class'SRClientSettings'.Static.IsFavorite(ForSalePickup) )
continue;
}
else if( ActiveCategory!=CPRL.ShopInventory[j].CatNum )
continue;
ForSaleWeapon = class<KFWeapon>(ForSalePickup.default.InventoryType);
// Remove single weld.
if( class'DualWeaponsManager'.Static.HasDualies(ForSaleWeapon,PlayerOwner().Pawn.Inventory) || (ForSalePickup.Default.VariantClasses.Length>0 && CheckGoldGunAvailable(ForSalePickup)) )
continue;
DualDivider = 1;
// Make cheaper.
if( ForSaleWeapon!=class'Dualies' && class'DualWeaponsManager'.Static.IsDualWeapon(ForSaleWeapon,SecType) && IsInInventoryWep(SecType) )
DualDivider = 2;
Blocker = None;
for( i=0; i<CPRL.CachePerks.Length; ++i )
if( !CPRL.CachePerks[i].PerkClass.Static.AllowWeaponInTrader(ForSalePickup,KFPRI,CPRL.CachePerks[i].CurrentLevel) )
{
Blocker = CPRL.CachePerks[i].PerkClass;
break;
}
if( Blocker!=None && Blocker.Default.DisableTag=="" )
continue;
ForSaleBuyable = AllocateEntry(CPRL);
ForSaleBuyable.ItemName = ForSalePickup.default.ItemName;
ForSaleBuyable.ItemDescription = ForSalePickup.default.Description;
ForSaleBuyable.ItemImage = ForSaleWeapon.default.TraderInfoTexture;
ForSaleBuyable.ItemWeaponClass = ForSaleWeapon;
ForSaleBuyable.ItemAmmoClass = ForSaleWeapon.default.FireModeClass[0].default.AmmoClass;
ForSaleBuyable.ItemPickupClass = ForSalePickup;
ForSaleBuyable.ItemCost = int((float(ForSalePickup.default.Cost)
* PlayerVeterancy.static.GetCostScaling(KFPRI, ForSalePickup)) / DualDivider);
ForSaleBuyable.ItemAmmoCost = 0;
ForSaleBuyable.ItemFillAmmoCost = 0;
ForSaleBuyable.ItemWeight = ForSaleWeapon.default.Weight;
if( DualDivider==2 )
ForSaleBuyable.ItemWeight -= SecType.Default.Weight;
ForSaleBuyable.ItemPower = ForSalePickup.default.PowerValue;
ForSaleBuyable.ItemRange = ForSalePickup.default.RangeValue;
ForSaleBuyable.ItemSpeed = ForSalePickup.default.SpeedValue;
ForSaleBuyable.ItemAmmoMax = 0;
ForSaleBuyable.ItemPerkIndex = ForSalePickup.default.CorrespondingPerkIndex;
// Make sure we mark the list as a sale list
ForSaleBuyable.bSaleList = true;
// Sort same perk weapons in front.
if( ForSalePickup.default.CorrespondingPerkIndex == PlayerVeterancy.default.PerkIndex )
{
ForSaleBuyables.Insert(PerkSaleOffset, 1);
i = PerkSaleOffset++;
}
else
{
i = ForSaleBuyables.Length;
ForSaleBuyables.Length = i+1;
}
ForSaleBuyables[i] = ForSaleBuyable;
DLCLocked = CPRL.ShopInventory[j].bDLCLocked;
if( DLCLocked==0 && Blocker!=None )
{
ForSaleBuyable.ItemCategorie = Blocker.Default.DisableTag$":"$Blocker.Default.DisableDescription;
DLCLocked = 3;
}
ForSaleBuyable.ItemAmmoCurrent = DLCLocked; // DLC info.
}
}
// Now Update the list
UpdateList();
}
function UpdateList()
{
local int i,j;
local ClientPerkRepLink CPRL;
CPRL = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
// Update the ItemCount and select the first item
ItemCount = CPRL.ShopCategories.Length + ForSaleBuyables.Length + 1;
// Clear the arrays
if ( ForSaleBuyables.Length < PrimaryStrings.Length )
{
PrimaryStrings.Length = ItemCount;
SecondaryStrings.Length = ItemCount;
CanBuys.Length = ItemCount;
ListPerkIcons.Length = ItemCount;
}
// Update categories
if( ActiveCategory>=-1 )
{
for( i=-1; i<(ActiveCategory+1); ++i )
{
if( i==-1 )
{
PrimaryStrings[j] = FavoriteGroupName;
ListPerkIcons[j] = None;
}
else
{
PrimaryStrings[j] = CPRL.ShopCategories[i].Name;
if( CPRL.ShopCategories[i].PerkIndex<CPRL.ShopPerkIcons.Length )
ListPerkIcons[j] = CPRL.ShopPerkIcons[CPRL.ShopCategories[i].PerkIndex];
else ListPerkIcons[j] = None;
}
CanBuys[j] = 3+i;
++j;
}
}
else
{
PrimaryStrings[j] = FavoriteGroupName;
CanBuys[j] = 2;
++j;
for( i=0; i<CPRL.ShopCategories.Length; ++i )
{
PrimaryStrings[j] = CPRL.ShopCategories[i].Name;
if( CPRL.ShopCategories[i].PerkIndex<CPRL.ShopPerkIcons.Length )
ListPerkIcons[j] = CPRL.ShopPerkIcons[CPRL.ShopCategories[i].PerkIndex];
else ListPerkIcons[j] = None;
CanBuys[j] = 3+i;
++j;
}
}
// Update the players inventory list
for ( i=0; i<ForSaleBuyables.Length; i++ )
{
PrimaryStrings[j] = ForSaleBuyables[i].ItemName;
SecondaryStrings[j] = "£" @ int(ForSaleBuyables[i].ItemCost);
if( ForSaleBuyables[i].ItemPerkIndex<CPRL.ShopPerkIcons.Length )
ListPerkIcons[j] = CPRL.ShopPerkIcons[ForSaleBuyables[i].ItemPerkIndex];
else ListPerkIcons[j] = None;
if( ForSaleBuyables[i].ItemAmmoCurrent!=0 )
{
CanBuys[j] = 0;
if( ForSaleBuyables[i].ItemAmmoCurrent==1 )
SecondaryStrings[j] = "DLC";
else if( ForSaleBuyables[i].ItemAmmoCurrent==2 )
SecondaryStrings[j] = "LOCKED";
else SecondaryStrings[j] = Left(ForSaleBuyables[i].ItemCategorie,InStr(ForSaleBuyables[i].ItemCategorie,":"));
}
else if ( ForSaleBuyables[i].ItemCost > PlayerOwner().PlayerReplicationInfo.Score ||
ForSaleBuyables[i].ItemWeight + KFHumanPawn(PlayerOwner().Pawn).CurrentWeight > KFHumanPawn(PlayerOwner().Pawn).MaxCarryWeight )
{
CanBuys[j] = 0;
}
else
{
CanBuys[j] = 1;
}
++j;
}
if( ActiveCategory>=-1 )
{
for( i=(ActiveCategory+1); i<CPRL.ShopCategories.Length; ++i )
{
PrimaryStrings[j] = CPRL.ShopCategories[i].Name;
if( CPRL.ShopCategories[i].PerkIndex<CPRL.ShopPerkIcons.Length )
ListPerkIcons[j] = CPRL.ShopPerkIcons[CPRL.ShopCategories[i].PerkIndex];
else ListPerkIcons[j] = None;
CanBuys[j] = 3+i;
++j;
}
}
if ( bNotify )
{
CheckLinkedObjects(Self);
}
if ( MyScrollBar != none )
{
MyScrollBar.AlignThumb();
}
bNeedsUpdate = false;
}
function DrawInvItem(Canvas Canvas, int CurIndex, float X, float Y, float Width, float Height, bool bSelected, bool bPending)
{
local float TempX, TempY, TempHeight;
local float StringHeight, StringWidth;
local Material M;
OnClickSound = CS_Click;
// Offset for the Background
TempX = X;
TempY = Y + ItemSpacing / 2.0;
// Initialize the Canvas
Canvas.Style = 1;
//Canvas.Font = class'ROHUD'.Static.GetSmallMenuFont(Canvas);
Canvas.SetDrawColor(255, 255, 255, 255);
// Draw Item Background
Canvas.SetPos(TempX, TempY);
if ( CanBuys[CurIndex]>1 )
{
bSelected = (ActiveCategory==(CanBuys[CurIndex]-3));
TempHeight = Height - 12;
TempY += 6;
if( ListPerkIcons[CurIndex]!=None )
{
Canvas.SetPos(X, Y+5);
if( bSelected )
M = SelectedCatPerkTex;
else M = CategoryPerkTex;
Canvas.DrawTileStretched(M, Height - 10, Height - 10);
TempX += (Height-10);
Width -= (Height-10);
}
Canvas.SetPos(TempX, TempY);
Canvas.DrawTileStretched(CategoryTex, Width, Height - 12);
// Draw category selection arrow.
Canvas.SetPos(TempX+Width-Height+7, Y+8);
if( bSelected )
M = CategoryArrowSel;
else M = CategoryArrow;
Canvas.DrawTile(M, Height - 16, Height - 16, 0, 0, M.MaterialUSize(), M.MaterialVSize());
// Draw perk icon
M = ListPerkIcons[CurIndex];
if( M!=None )
{
Canvas.SetPos(X + 2, Y + 7);
Canvas.DrawTile(M, Height - 14, Height - 14, 0, 0, M.MaterialUSize(), M.MaterialVSize());
}
}
else
{
if ( CanBuys[CurIndex]==0 )
{
Canvas.DrawTileStretched(DisabledItemBackgroundLeft, Height - ItemSpacing, Height - ItemSpacing);
TempX += ((Height - ItemSpacing) - 1);
TempHeight = Height - 12;
TempY += 6;//(Height - TempHeight) / 2;
Canvas.SetPos(TempX, TempY);
Canvas.DrawTileStretched(DisabledItemBackgroundRight, Width - (Height - ItemSpacing), Height - 12);
}
else if ( bSelected )
{
Canvas.DrawTileStretched(SelectedItemBackgroundLeft, Height - ItemSpacing, Height - ItemSpacing);
TempX += ((Height - ItemSpacing) - 1);
TempHeight = Height - 12;
TempY += 6;//(Height - TempHeight) / 2;
Canvas.SetPos(TempX, TempY);
Canvas.DrawTileStretched(SelectedItemBackgroundRight, Width - (Height - ItemSpacing), Height - 12);
}
else
{
Canvas.DrawTileStretched(ItemBackgroundLeft, Height - ItemSpacing, Height - ItemSpacing);
TempX += ((Height - ItemSpacing) - 1);
TempHeight = Height - 12;
TempY += 6;//(Height - TempHeight) / 2;
Canvas.SetPos(TempX, TempY);
Canvas.DrawTileStretched(ItemBackgroundRight, Width - (Height - ItemSpacing), Height - 12);
}
M = ListPerkIcons[CurIndex];
if( M!=None )
{
Canvas.SetPos(X + 4, Y + 4);
Canvas.DrawTile(M, Height - 8, Height - 8, 0, 0, M.MaterialUSize(), M.MaterialVSize());
}
}
// Select Text color
if ( CurIndex == MouseOverIndex )
{
Canvas.SetDrawColor(255, 255, 255, 255);
}
else
{
Canvas.SetDrawColor(0, 0, 0, 255);
}
// Draw the item's name or category
Canvas.TextSize(PrimaryStrings[CurIndex], StringWidth, StringHeight);
Canvas.SetPos(TempX + (0.2 * Height), TempY + ((TempHeight - StringHeight) / 2));
Canvas.DrawText(PrimaryStrings[CurIndex]);
// Draw the item's price
if ( CanBuys[CurIndex] <2 )
{
Canvas.TextSize(SecondaryStrings[CurIndex], StringWidth, StringHeight);
Canvas.SetPos((TempX - Height) + Width - (StringWidth + (0.2 * Height)), TempY + ((TempHeight - StringHeight) / 2));
Canvas.DrawText(SecondaryStrings[CurIndex]);
}
/* else
{
Canvas.TextSize(WeaponGroupText, StringWidth, StringHeight);
Canvas.SetPos((TempX - Height) + Width - (StringWidth + (0.2 * Height)), TempY + ((TempHeight - StringHeight) / 2));
Canvas.DrawText(WeaponGroupText);
}*/
Canvas.SetDrawColor(255, 255, 255, 255);
}
function IndexChanged(GUIComponent Sender)
{
if ( Index>=0 && CanBuys[Index]==0 && (Index-SelectionOffset)>=0 && ForSaleBuyables[Index-SelectionOffset].ItemAmmoCurrent==0 )
{
if ( ForSaleBuyables[Index-SelectionOffset].ItemCost > PlayerOwner().PlayerReplicationInfo.Score )
PlayerOwner().Pawn.DemoPlaySound(TraderSoundTooExpensive, SLOT_Interface, 2.0);
else if ( ForSaleBuyables[Index-SelectionOffset].ItemWeight + KFHumanPawn(PlayerOwner().Pawn).CurrentWeight > KFHumanPawn(PlayerOwner().Pawn).MaxCarryWeight )
PlayerOwner().Pawn.DemoPlaySound(TraderSoundTooHeavy, SLOT_Interface, 2.0);
}
Super(GUIVertList).IndexChanged(Sender);
}
defaultproperties
{
ActiveCategory=-2
WeaponGroupText="Weapon group"
CategoryTex=Texture'KF_InterfaceArt_tex.Menu.Thin_border'
CategoryPerkTex=Texture'KF_InterfaceArt_tex.Menu.button_Highlight'
SelectedCatPerkTex=Texture'KF_InterfaceArt_tex.Menu.button_pressed'
CategoryArrow=Texture'KF_InterfaceArt_tex.Menu.LeftMark'
CategoryArrowSel=Texture'KF_InterfaceArt_tex.Menu.DownMark'
}

View file

@ -0,0 +1,18 @@
//-----------------------------------------------------------
//
//-----------------------------------------------------------
class SRBuyMenuSaleListBox extends KFBuyMenuSaleListBox;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
DefaultListClass = string(Class'SRBuyMenuSaleList');
Super.InitComponent(MyController,MyOwner);
}
function GUIBuyable GetSelectedBuyable()
{
return SRBuyMenuSaleList(List).GetSelectedBuyable();
}
defaultproperties
{
}

View file

@ -0,0 +1,57 @@
Class SRClientSettings extends Object
PerObjectConfig
Config(ServerPerksClient);
var private transient SRClientSettings Ref;
var config array<name> Fav;
static final function SRClientSettings GetSettings()
{
if( Default.Ref==None )
Default.Ref = New(None,"Settings")Class'SRClientSettings';
return Default.Ref;
}
static final function bool IsFavorite( class<Pickup> WC )
{
local SRClientSettings S;
local int i;
S = GetSettings();
for( i=0; i<S.Fav.Length; ++i )
if( S.Fav[i]==WC.Name )
return true;
return false;
}
static final function AddFavorite( class<Pickup> WC )
{
local SRClientSettings S;
local int i;
S = GetSettings();
for( i=0; i<S.Fav.Length; ++i )
if( S.Fav[i]==WC.Name )
return;
S.Fav.Length = i+1;
S.Fav[i] = WC.Name;
S.SaveConfig();
}
static final function RemoveFavorite( class<Pickup> WC )
{
local SRClientSettings S;
local int i;
S = GetSettings();
for( i=0; i<S.Fav.Length; ++i )
if( S.Fav[i]==WC.Name )
{
S.Fav.Remove(i,1);
S.SaveConfig();
return;
}
}
defaultproperties
{
}

View file

@ -0,0 +1,58 @@
Class SRCustomProgress extends ReplicationInfo
Abstract;
var() localized string ProgressName;
var ClientPerkRepLink RepLink;
var SRCustomProgress NextLink;
replication
{
reliable if( Role==ROLE_Authority && bNetOwner )
NextLink;
}
simulated function string GetProgress();
simulated function int GetProgressInt()
{
return int(GetProgress());
}
simulated function string GetDisplayString()
{
return GetProgress();
}
function SetProgress( string S );
function IncrementProgress( int Count );
final function ValueUpdated()
{
if( RepLink.StatObject!=None )
RepLink.StatObject.NotifyStatChanged();
}
simulated final function string GetTimeText( int V )
{
local int Hours, Minutes;
Minutes = V / 60;
Hours = Minutes / 60;
V -= (Minutes * 60);
Minutes -= (Hours * 60);
return Eval(Hours<10,"0"$Hours,string(Hours))$":"$Eval(Minutes<10,"0"$Minutes,string(Minutes))$":"$Eval(V<10,"0"$V,string(V));
}
// Called when stat owner killed or was killed by a monster.
function NotifyPlayerKill( Pawn Killed, class<DamageType> damageType );
function NotifyPlayerKilled( Pawn Killer, class<DamageType> damageType );
defaultproperties
{
ProgressName="Lazy modder! Kill him!!"
bOnlyRelevantToOwner=True
bAlwaysRelevant=False
NetUpdateFrequency=2.000000
}

View file

@ -0,0 +1,35 @@
Class SRCustomProgressFloat extends SRCustomProgress
Abstract;
var float CurrentValue;
replication
{
reliable if( Role==ROLE_Authority && bNetOwner )
CurrentValue;
}
simulated function string GetProgress()
{
return string(CurrentValue);
}
simulated function int GetProgressInt()
{
return CurrentValue;
}
function SetProgress( string S )
{
CurrentValue = float(S);
}
function IncrementProgress( int Count )
{
CurrentValue+=Count;
ValueUpdated();
}
defaultproperties
{
}

View file

@ -0,0 +1,35 @@
Class SRCustomProgressInt extends SRCustomProgress
Abstract;
var int CurrentValue;
replication
{
reliable if( Role==ROLE_Authority && bNetOwner )
CurrentValue;
}
simulated function string GetProgress()
{
return string(CurrentValue);
}
simulated function int GetProgressInt()
{
return CurrentValue;
}
function SetProgress( string S )
{
CurrentValue = int(S);
}
function IncrementProgress( int Count )
{
CurrentValue+=Count;
ValueUpdated();
}
defaultproperties
{
}

View file

@ -0,0 +1,50 @@
//=============================================================================
// The Trader menu with a tab for the store and the perks
//=============================================================================
class SRGUIBuyMenu extends GUIBuyMenu;
function bool NotifyLevelChange()
{
bPersistent = false;
return true;
}
function InitTabs()
{
local SRKFTab_BuyMenu B;
B = SRKFTab_BuyMenu(c_Tabs.AddTab(PanelCaption[0], string(Class'SRKFTab_BuyMenu'),, PanelHint[0]));
c_Tabs.AddTab(PanelCaption[1], string(Class'SRKFTab_Perks'),, PanelHint[1]);
SRBuyMenuFilter(BuyMenuFilter).SaleListBox = SRBuyMenuSaleList(B.SaleSelect.List);
}
defaultproperties
{
Begin Object Class=SRKFQuickPerkSelect Name=QS
WinTop=0.011906
WinLeft=0.008008
WinWidth=0.316601
WinHeight=0.082460
OnDraw=QS.MyOnDraw
End Object
QuickPerkSelect=SRKFQuickPerkSelect'ServerPerks.SRGUIBuyMenu.QS'
Begin Object Class=SRBuyMenuFilter Name=SRFilter
WinTop=0.051000
WinLeft=0.670000
WinWidth=0.305000
WinHeight=0.082460
OnDraw=SRFilter.MyOnDraw
End Object
BuyMenuFilter=SRBuyMenuFilter'ServerPerks.SRGUIBuyMenu.SRFilter'
Begin Object Class=SRWeightBar Name=WeightB
WinTop=0.945302
WinLeft=0.055266
WinWidth=0.443888
WinHeight=0.053896
OnDraw=WeightB.MyOnDraw
End Object
WeightBar=SRWeightBar'ServerPerks.SRGUIBuyMenu.WeightB'
}

View file

@ -0,0 +1,96 @@
class SRGUIBuyWeaponInfoPanel extends GUIBuyWeaponInfoPanel;
function Opened( GUIComponent Sender )
{
super(GUIBuyDescInfoPanel).Opened( Sender );
}
function Display(GUIBuyable NewBuyable)
{
if ( NewBuyable == none || NewBuyable.bIsFirstAidKit || NewBuyable.bIsVest )
{
b_power.SetValue(0);
b_power.SetVisibility(false);
b_speed.SetValue(0);
b_speed.SetVisibility(false);
b_range.SetValue(0);
b_range.SetVisibility(false);
ItemPower.SetVisibility(false);
ItemRange.SetVisibility(false);
ItemSpeed.SetVisibility(false);
WeightLabel.SetVisibility(false);
WeightLabelBG.SetVisibility(false);
FavoriteButton.SetVisibility(false);
}
else
{
b_power.SetValue(NewBuyable.ItemPower);
b_speed.SetValue(NewBuyable.ItemSpeed);
b_range.SetValue(NewBuyable.ItemRange);
b_power.SetVisibility(true);
b_speed.SetVisibility(true);
b_range.SetVisibility(true);
ItemPower.SetVisibility(true);
ItemRange.SetVisibility(true);
ItemSpeed.SetVisibility(true);
WeightLabel.SetVisibility(true);
WeightLabelBG.SetVisibility(true);
if( NewBuyable.bSaleList )
{
FavoriteButton.SetVisibility(true);
}
else
{
FavoriteButton.SetVisibility(false);
}
bFavorited = (NewBuyable.ItemPickupClass!=None && Class'SRClientSettings'.Static.IsFavorite( NewBuyable.ItemPickupClass ));
RefreshFavoriteButton();
}
if ( NewBuyable != none )
{
ItemName.Caption = NewBuyable.ItemName;
ItemNameBG.bVisible = true;
ItemImage.Image = NewBuyable.ItemImage;
WeightLabel.Caption = Repl(Weight, "%i", int(NewBuyable.ItemWeight));
OldPickupClass = NewBuyable.ItemPickupClass;
}
else
{
ItemName.Caption = "";
ItemNameBG.bVisible = false;
ItemImage.Image = none;
WeightLabel.Caption = "";
}
Super(GUIBuyDescInfoPanel).Display(NewBuyable);
}
function bool InternalOnClick( GUIComponent Sender )
{
if( Sender == FavoriteButton )
{
if( OldPickupClass != none )
{
if( bFavorited )
Class'SRClientSettings'.Static.RemoveFavorite(OldPickupClass);
else Class'SRClientSettings'.Static.AddFavorite(OldPickupClass);
bFavorited = !bFavorited;
RefreshFavoriteButton();
}
}
return true;
}
defaultproperties
{
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,519 @@
//=============================================================================
// SRHumanPawn
//=============================================================================
class SRHumanPawn extends KFHumanPawn_Story;
var ClientPerkRepLink PerkLink;
var transient float CashTossTimer,LongTossCashTimer;
var transient byte LongTossCashCount;
// Override bad coding in StoryGame
simulated function Fire( optional float F )
{
Super(Pawn).Fire(F);
}
function AddDefaultInventory()
{
if( KFStoryGameInfo(Level.Game)!=none )
Super.AddDefaultInventory();
else Super(KFHumanPawn).AddDefaultInventory();
}
function ServerSellAmmo( Class<Ammunition> AClass );
final function bool HasWeaponClass( class<Inventory> IC, optional out Inventory Res )
{
local Inventory I;
for ( I=Inventory; I!=None; I=I.Inventory )
if( I.Class==IC )
{
Res = I;
return true;
}
return false;
}
final function ClientPerkRepLink FindStats()
{
local LinkedReplicationInfo L;
if( Controller==None || Controller.PlayerReplicationInfo==None )
return None;
for( L=Controller.PlayerReplicationInfo.CustomReplicationInfo; L!=None; L=L.NextReplicationInfo )
if( ClientPerkRepLink(L)!=None )
return ClientPerkRepLink(L);
return None;
}
function ServerBuyWeapon( Class<Weapon> WClass, float Weight )
{
local float Price;
local int OtherPrice;
local Inventory I,OI;
local class<KFWeapon> SecType;
if( !CanBuyNow() || Class<KFWeapon>(WClass)==None || Class<KFWeaponPickup>(WClass.Default.PickupClass)==None || HasWeaponClass(WClass) )
Return;
// Validate if allowed to buy that weapon.
if( PerkLink==None )
PerkLink = FindStats();
if( PerkLink!=None && !PerkLink.CanBuyPickup(Class<KFWeaponPickup>(WClass.Default.PickupClass)) )
return;
Price = class<KFWeaponPickup>(WClass.Default.PickupClass).Default.Cost;
if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
Price *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), WClass.Default.PickupClass);
Weight = Class<KFWeapon>(WClass).Default.Weight;
if( class'DualWeaponsManager'.Static.IsDualWeapon(WClass,SecType) )
{
if( WClass!=class'Dualies' && HasWeaponClass(SecType,OI) )
{
Weight-=SecType.Default.Weight;
Price*=0.5f;
OtherPrice = KFWeapon(OI).SellValue;
if( OtherPrice==-1 )
{
OtherPrice = class<KFWeaponPickup>(SecType.Default.PickupClass).Default.Cost * 0.75;
if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
OtherPrice *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), SecType.Default.PickupClass);
}
}
}
else if( class'DualWeaponsManager'.Static.HasDualies(WClass,Inventory) )
return;
Price = int(Price); // Truncuate price.
if( Weight>0 && !CanCarry(Weight) )
{
ClientMessage("Error: "$WClass.Name$" is too heavy ("$CurrentWeight$"+"$Weight$">"$MaxCarryWeight$")");
return;
}
if ( PlayerReplicationInfo.Score<Price )
{
ClientMessage("Error: "$WClass.Name$" is too expensive ("$int(Price)$">"$int(PlayerReplicationInfo.Score)$")");
Return;
}
I = Spawn(WClass);
if ( I != none )
{
if ( KFGameType(Level.Game) != none )
KFGameType(Level.Game).WeaponSpawned(I);
KFWeapon(I).UpdateMagCapacity(PlayerReplicationInfo);
KFWeapon(I).FillToInitialAmmo();
KFWeapon(I).SellValue = Price * 0.75;
if( OtherPrice>0 )
KFWeapon(I).SellValue+=OtherPrice;
I.GiveTo(self);
PlayerReplicationInfo.Score -= Price;
ClientForceChangeWeapon(I);
}
else ClientMessage("Error: "$WClass.Name$" failed to spawn.");
SetTraderUpdate();
}
function ServerSellWeapon( Class<Weapon> WClass )
{
local Inventory I;
local KFWeapon NewWep;
local float Price;
local class<KFWeapon> SecType;
if ( !CanBuyNow() || Class<KFWeapon>(WClass) == none || Class<KFWeaponPickup>(WClass.Default.PickupClass)==none
|| Class<KFWeapon>(WClass).Default.bKFNeverThrow )
{
SetTraderUpdate();
Return;
}
for ( I = Inventory; I != none; I = I.Inventory )
{
if ( I.Class==WClass )
{
if ( KFWeapon(I) != none && KFWeapon(I).SellValue != -1 )
Price = KFWeapon(I).SellValue;
else
{
Price = (class<KFWeaponPickup>(WClass.default.PickupClass).default.Cost * 0.75);
if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
Price *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), WClass.Default.PickupClass);
}
if( class'DualWeaponsManager'.Static.IsDualWeapon(WClass,SecType) )
{
NewWep = Spawn(SecType);
if( WClass!=class'Dualies' )
{
Price *= 0.5f;
NewWep.SellValue = Price;
}
NewWep.GiveTo(self);
}
if ( I==Weapon || I==PendingWeapon )
{
ClientCurrentWeaponSold();
}
PlayerReplicationInfo.Score += int(Price);
I.Destroy();
SetTraderUpdate();
if ( KFGameType(Level.Game)!=none )
KFGameType(Level.Game).WeaponDestroyed(WClass);
return;
}
}
}
simulated function AddBlur(Float BlurDuration, float Intensity)
{
if( KFPC!=none && Viewport(KFPC.Player)!=None )
Super.AddBlur(BlurDuration,Intensity);
}
simulated function DoHitCamEffects(vector HitDirection, float JarrScale, float BlurDuration, float JarDurationScale )
{
if( KFPC!=none && Viewport(KFPC.Player)!=None )
Super.DoHitCamEffects(HitDirection,JarrScale,BlurDuration,JarDurationScale);
}
simulated function StopHitCamEffects()
{
if( KFPC!=none && Viewport(KFPC.Player)!=None )
Super.StopHitCamEffects();
}
exec function TossCash( int Amount )
{
// To fix cash tossing exploit.
if( CashTossTimer<Level.TimeSeconds && (LongTossCashTimer<Level.TimeSeconds || LongTossCashCount<20) )
{
Super.TossCash(Max(Amount,50));
CashTossTimer = Level.TimeSeconds+0.1f;
if( LongTossCashTimer<Level.TimeSeconds )
{
LongTossCashTimer = Level.TimeSeconds+5.f;
LongTossCashCount = 0;
}
else ++LongTossCashCount;
}
}
function PlayDyingAnimation(class<DamageType> DamageType, vector HitLoc)
{
local vector shotDir, hitLocRel, deathAngVel, shotStrength;
local float maxDim;
local string RagSkelName;
local KarmaParamsSkel skelParams;
local bool PlayersRagdoll;
local PlayerController pc;
if ( Level.NetMode != NM_DedicatedServer )
{
// Is this the local player's ragdoll?
if(OldController != None)
pc = PlayerController(OldController);
if( pc != none && pc.ViewTarget == self )
PlayersRagdoll = true;
// In low physics detail, if we were not just controlling this pawn,
// and it has not been rendered in 3 seconds, just destroy it.
if( !PlayersRagdoll && (Level.TimeSeconds-LastRenderTime)>3 )
{
GoTo'NonRagdoll';
return;
}
// Try and obtain a rag-doll setup. Use optional 'override' one out of player record first, then use the species one.
if( RagdollOverride != "")
RagSkelName = RagdollOverride;
else if(Species != None)
RagSkelName = Species.static.GetRagSkelName( GetMeshName() );
else RagSkelName = "Male1"; // Otherwise assume it is Male1 ragdoll were after here.
KMakeRagdollAvailable();
if( KIsRagdollAvailable() && RagSkelName != "" )
{
skelParams = KarmaParamsSkel(KParams);
skelParams.KSkeleton = RagSkelName;
// Stop animation playing.
StopAnimating(true);
if( DamageType != None )
{
if ( DamageType.default.bLeaveBodyEffect )
TearOffMomentum = vect(0,0,0);
if( DamageType.default.bKUseOwnDeathVel )
{
RagDeathVel = DamageType.default.KDeathVel;
RagDeathUpKick = DamageType.default.KDeathUpKick;
}
}
// Set the dude moving in direction he was shot in general
shotDir = Normal(GetTearOffMomemtum());
shotStrength = RagDeathVel * shotDir;
// Calculate angular velocity to impart, based on shot location.
hitLocRel = TakeHitLocation - Location;
// We scale the hit location out sideways a bit, to get more spin around Z.
hitLocRel.X *= RagSpinScale;
hitLocRel.Y *= RagSpinScale;
// If the tear off momentum was very small for some reason, make up some angular velocity for the pawn
if( VSize(GetTearOffMomemtum()) < 0.01 )
{
//Log("TearOffMomentum magnitude of Zero");
deathAngVel = VRand() * 18000.0;
}
else deathAngVel = RagInvInertia * (hitLocRel Cross shotStrength);
// Set initial angular and linear velocity for ragdoll.
// Scale horizontal velocity for characters - they run really fast!
if ( DamageType.Default.bRubbery )
skelParams.KStartLinVel = vect(0,0,0);
if ( Damagetype.default.bKUseTearOffMomentum )
skelParams.KStartLinVel = GetTearOffMomemtum() + Velocity;
else
{
skelParams.KStartLinVel.X = 0.6 * Velocity.X;
skelParams.KStartLinVel.Y = 0.6 * Velocity.Y;
skelParams.KStartLinVel.Z = 1.0 * Velocity.Z;
skelParams.KStartLinVel += shotStrength;
}
// If not moving downwards - give extra upward kick
if( !DamageType.default.bLeaveBodyEffect && !DamageType.Default.bRubbery && (Velocity.Z > -10) )
skelParams.KStartLinVel.Z += RagDeathUpKick;
if ( DamageType.Default.bRubbery )
{
Velocity = vect(0,0,0);
skelParams.KStartAngVel = vect(0,0,0);
}
else
{
skelParams.KStartAngVel = deathAngVel;
// Set up deferred shot-bone impulse
maxDim = Max(CollisionRadius, CollisionHeight);
skelParams.KShotStart = TakeHitLocation - (1 * shotDir);
skelParams.KShotEnd = TakeHitLocation + (2*maxDim*shotDir);
skelParams.KShotStrength = RagShootStrength;
}
// If this damage type causes convulsions, turn them on here.
if(DamageType != None && DamageType.default.bCauseConvulsions)
{
RagConvulseMaterial=DamageType.default.DamageOverlayMaterial;
skelParams.bKDoConvulsions = true;
}
// Turn on Karma collision for ragdoll.
KSetBlockKarma(true);
// Set physics mode to ragdoll.
// This doesn't actaully start it straight away, it's deferred to the first tick.
SetPhysics(PHYS_KarmaRagdoll);
// If viewing this ragdoll, set the flag to indicate that it is 'important'
if( PlayersRagdoll )
skelParams.bKImportantRagdoll = true;
skelParams.bRubbery = DamageType.Default.bRubbery;
bRubbery = DamageType.Default.bRubbery;
skelParams.KActorGravScale = RagGravScale;
return;
}
// jag
}
NonRagdoll:
// non-ragdoll death fallback
LifeSpan = 0.2f;
}
function float AssessThreatTo(KFMonsterController Monster, optional bool CheckDistance)
{
local float ThreatRating;
local Inventory CurInv;
local KF_StoryInventoryItem StoryInv;
ThreatRating = FMax(Super(KFHumanPawn).AssessThreatTo(Monster,CheckDistance),0.1f);
/* Factor in story Items which adjust your desirability to ZEDs */
for ( CurInv = Inventory; CurInv != none; CurInv = CurInv.Inventory )
{
StoryInv = KF_StoryInventoryItem(CurInv);
if(StoryInv != none)
ThreatRating *= StoryInv.AIThreatModifier;
}
return ThreatRating;
}
simulated final function int GetFloorSurface()
{
local int SurfaceTypeID;
local actor A;
local vector HL,HN,Start,End;
local material FloorMat;
if ( (Base!=None) && (!Base.IsA('LevelInfo')) && (Base.SurfaceType!=0) )
SurfaceTypeID = Base.SurfaceType;
else
{
Start = Location - Vect(0,0,1)*CollisionHeight;
End = Start - Vect(0,0,16);
A = Trace(hl,hn,End,Start,false,,FloorMat);
if (FloorMat !=None)
SurfaceTypeID = FloorMat.SurfaceType;
}
return SurfaceTypeID;
}
simulated function Sound GetSound(xPawnSoundGroup.ESoundType soundType)
{
local int SurfaceTypeID;
if( SoundGroupClass==None )
SoundGroupClass = Class'KFMaleSoundGroup';
if( soundType == EST_Land || soundType == EST_Jump )
SurfaceTypeID = GetFloorSurface();
return SoundGroupClass.static.GetSound(soundType, SurfaceTypeID);
}
// The player wants to switch to weapon group number F.
simulated function SwitchWeapon(byte F)
{
local Weapon DesiredWeap;
local bool AllowSwitch;
// Fixed script warnings.
if( Weapon!=None && Weapon.Inventory!=None )
DesiredWeap = Weapon.Inventory.WeaponChange(F, false);
if(DesiredWeap == none && Inventory!=None )
DesiredWeap = Inventory.WeaponChange(F, true);
if(DesiredWeap != none)
AllowSwitch = AllowHoldWeapon(DesiredWeap);
if( AllowSwitch )
Super(KFPawn).SwitchWeapon(F);
}
simulated function tick(float DeltaTime)
{
local KF_StoryPRI PRI;
super(KFPawn).Tick(DeltaTime);
if( IsLocallyControlled() && !bUsingHitBlur && BlurFadeOutTime > 0 )
{
BlurFadeOutTime -= DeltaTime;
DeltaTime = BlurFadeOutTime/StartingBlurFadeOutTime * CurrentBlurIntensity;
if( BlurFadeOutTime <= 0 )
{
BlurFadeOutTime = 0;
StopHitCamEffects();
}
else if( bUseBlurEffect && KFPC!=none && !KFPC.PostFX_IsReady() )
{
if( CameraEffectFound != none )
UnderWaterBlur(CameraEffectFound).BlurAlpha = Lerp( DeltaTime, 255, UnderWaterBlur(CameraEffectFound).default.BlurAlpha );
else KFPC.SetBlur(DeltaTime);
}
}
/* Replicated Location stuff - for tracking this pawn's position to display icons when its not relevant */
PRI = KF_StoryPRI(PlayerReplicationInfo);
if(PRI != none && PRI.GetFloatingIconMat() != none)
{
if(Role == Role_Authority) // server authoritative
{
if(PRI.GetOwnerPawn() != self)
{
PRI.SetOwnerPawn(self);
PRI.NetUpdateTime = Level.TimeSeconds - 1;
}
KF_StoryPRI(PlayerReplicationInfo).SetReplicatedPawnLoc(GetHoverIconPosition());
}
else if(bDeleteMe || bPendingDelete) // simulated proxy.
{
PRI.SetOwnerPawn(none);
PRI.NetUpdateTime = Level.TimeSeconds - 1;
}
}
}
simulated function SetWeaponAttachment(WeaponAttachment NewAtt)
{
local byte i;
Super.SetWeaponAttachment(NewAtt);
if( KFWeaponAttachment(WeaponAttachment)!=None )
{
// Veryify valid animations.
for( i=0; i<4; ++i )
{
DoubleJumpAnims[i] = TakeoffAnims[i];
if( !HasAnim(MovementAnims[i]) )
MovementAnims[i] = Default.MovementAnims[i];
if( !HasAnim(WalkAnims[i]) )
MovementAnims[i] = Default.WalkAnims[i];
}
if( !HasAnim(IdleWeaponAnim) )
MovementAnims[i] = Default.IdleWeaponAnim;
if( !HasAnim(IdleRestAnim) )
MovementAnims[i] = Default.IdleRestAnim;
if( !HasAnim(IdleChatAnim) )
MovementAnims[i] = Default.IdleChatAnim;
}
}
defaultproperties
{
InvisMaterial=Shader'KF_Specimens_Trip_T.patriarch_invisible'
WallDodgeAnims(0)="JumpF_Takeoff"
WallDodgeAnims(1)="JumpL_Takeoff"
WallDodgeAnims(2)="JumpL_Takeoff"
WallDodgeAnims(3)="JumpR_Takeoff"
MovementAnims(0)="JogF_Pipe"
MovementAnims(1)="JogB_Pipe"
MovementAnims(2)="JogL_Pipe"
MovementAnims(3)="JogR_Pipe"
SwimAnims(0)="WalkF_Flamethrower"
SwimAnims(1)="WalkB_Flamethrower"
SwimAnims(2)="WalkL_Flamethrower"
SwimAnims(3)="WalkR_Flamethrower"
CrouchAnims(0)="CHwalkF_Pipe"
CrouchAnims(1)="CHwalkB_Pipe"
CrouchAnims(2)="CHwalkL_Pipe"
CrouchAnims(3)="CHwalkR_Pipe"
WalkAnims(0)="WalkF_Flamethrower"
WalkAnims(1)="WalkB_Flamethrower"
WalkAnims(2)="WalkL_Flamethrower"
WalkAnims(3)="WalkR_Flamethrower"
DoubleJumpAnims(0)="JumpF_Takeoff"
DoubleJumpAnims(1)="JumpL_Takeoff"
DoubleJumpAnims(2)="JumpL_Takeoff"
DoubleJumpAnims(3)="JumpR_Takeoff"
IdleWeaponAnim="Idle_Pipe"
IdleRestAnim="Idle_Pipe"
IdleChatAnim="Idle_Pipe"
}

View file

@ -0,0 +1,549 @@
Class SRInvasionLoginMenu extends UT2K4PlayerLoginMenu;
var() noexport bool bNetGame;
var bool bOldSpectator;
var automated GUIButton b_Settings, b_Browser, b_Quit, b_Favs,
b_Leave, b_MapVote, b_KickVote, b_MatchSetup, b_Spec, b_Profile;
var GUIStyles PlayerStyle;
var array<SRMenuAddition> AddOnList;
var int CurTabOrder;
simulated final function GUIButton AddControlButton( string Cap, optional string Hint )
{
local GUIButton G;
G = GUIButton(AddComponent(string(Class'GUIButton')));
G.Caption = Cap;
G.Hint = Hint;
G.StyleName = "SquareButton";
G.OnKeyEvent = G.InternalOnKeyEvent;
G.WinLeft = 0.725;
G.WinTop = 0.89;
G.WinWidth = 0.2;
G.WinHeight = 0.05;
G.bAutoSize = True;
G.TabOrder = CurTabOrder++;
return G;
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local int i;
local string s;
local eFontScale FS;
local SRMenuAddition M;
// Setup panel classes.
Panels[0].ClassName = string(Class'SRTab_ServerNews');
Panels[1].ClassName = string(Class'SRTab_MidGamePerks');
Panels[2].ClassName = string(Class'SRTab_MidGameVoiceChat');
Panels[3].ClassName = string(Class'SRTab_MidGameHelp');
Panels[4].ClassName = string(Class'SRTab_MidGameStats');
// Setup localization.
Panels[1].Caption = Class'KFInvasionLoginMenu'.Default.Panels[1].Caption;
Panels[2].Caption = Class'KFInvasionLoginMenu'.Default.Panels[2].Caption;
Panels[3].Caption = Class'KFInvasionLoginMenu'.Default.Panels[3].Caption;
Panels[1].Hint = Class'KFInvasionLoginMenu'.Default.Panels[1].Hint;
Panels[2].Hint = Class'KFInvasionLoginMenu'.Default.Panels[2].Hint;
Panels[3].Hint = Class'KFInvasionLoginMenu'.Default.Panels[3].Hint;
b_Spec.Caption=class'KFTab_MidGamePerks'.default.b_Spec.Caption;
b_MatchSetup.Caption=class'KFTab_MidGamePerks'.default.b_MatchSetup.Caption;
b_KickVote.Caption=class'KFTab_MidGamePerks'.default.b_KickVote.Caption;
b_MapVote.Caption=class'KFTab_MidGamePerks'.default.b_MapVote.Caption;
b_Quit.Caption=class'KFTab_MidGamePerks'.default.b_Quit.Caption;
b_Favs.Caption=class'KFTab_MidGamePerks'.default.b_Favs.Caption;
b_Favs.Hint=class'KFTab_MidGamePerks'.default.b_Favs.Hint;
b_Settings.Caption=class'KFTab_MidGamePerks'.default.b_Settings.Caption;
b_Browser.Caption=class'KFTab_MidGamePerks'.default.b_Browser.Caption;
Super.InitComponent(MyController, MyOwner);
// Mod menus
foreach MyController.ViewportOwner.Actor.DynamicActors(class'SRMenuAddition',M)
if( M.bHasInit )
{
AddOnList[AddOnList.Length] = M;
M.NotifyMenuOpen(Self,MyController);
}
s = GetSizingCaption();
for ( i = 0; i < Controls.Length; i++ )
{
if ( GUIButton(Controls[i]) != None )
{
GUIButton(Controls[i]).bAutoSize = true;
GUIButton(Controls[i]).SizingCaption = s;
GUIButton(Controls[i]).AutoSizePadding.HorzPerc = 0.04;
GUIButton(Controls[i]).AutoSizePadding.VertPerc = 0.5;
}
}
s = class'KFTab_MidGamePerks'.default.PlayerStyleName;
PlayerStyle = MyController.GetStyle(s, fs);
InitGRI();
}
function Opened(GUIComponent Sender)
{
local int i;
Super.Opened(Sender);
for( i=0; i<AddOnList.Length; ++i )
AddOnList[i].NotifyMenuShown();
}
event Closed(GUIComponent Sender, bool bCancelled)
{
local int i;
Super.Closed(Sender,bCancelled);
for( i=0; i<AddOnList.Length; ++i )
AddOnList[i].NotifyMenuClosed();
}
function string GetSizingCaption()
{
local int i;
local string s;
for ( i = 0; i < Controls.Length; i++ )
{
if ( GUIButton(Controls[i]) != none )
{
if ( s == "" || Len(GUIButton(Controls[i]).Caption) > Len(s) )
{
s = GUIButton(Controls[i]).Caption;
}
}
}
return s;
}
function GameReplicationInfo GetGRI()
{
return PlayerOwner().GameReplicationInfo;
}
function InitGRI()
{
local PlayerController PC;
local GameReplicationInfo GRI;
GRI = GetGRI();
PC = PlayerOwner();
if ( PC == none || PC.PlayerReplicationInfo == none || GRI == none )
return;
bInit = False;
bNetGame = PC.Level.NetMode != NM_StandAlone;
if ( bNetGame )
b_Leave.Caption = class'KFTab_MidGamePerks'.default.LeaveMPButtonText;
else b_Leave.Caption = class'KFTab_MidGamePerks'.default.LeaveSPButtonText;
bOldSpectator = PC.PlayerReplicationInfo.bOnlySpectator;
if ( bOldSpectator )
b_Spec.Caption = class'KFTab_MidGamePerks'.default.JoinGameButtonText;
else b_Spec.Caption = class'KFTab_MidGamePerks'.default.SpectateButtonText;
SetupGroups();
//InitLists();
}
function float ItemHeight(Canvas C)
{
local float XL, YL, H;
local eFontScale f;
f=FNS_Medium;
PlayerStyle.TextSize(C, MSAT_Blurry, "Wqz, ", XL, H, F);
if ( C.ClipX > 640 && bNetGame )
PlayerStyle.TextSize(C, MSAT_Blurry, "Wqz, ", XL, YL, FNS_Small);
H += YL;
H += (H * 0.2);
return h;
}
function SetupGroups()
{
local PlayerController PC;
PC = PlayerOwner();
if ( PC.Level.NetMode != NM_Client )
{
RemoveComponent(b_Favs);
RemoveComponent(b_Browser);
}
else if ( CurrentServerIsInFavorites() )
{
DisableComponent(b_Favs);
}
if ( PC.Level.NetMode == NM_StandAlone )
{
RemoveComponent(b_MapVote, True);
RemoveComponent(b_MatchSetup, True);
RemoveComponent(b_KickVote, True);
}
else if ( PC.VoteReplicationInfo != None )
{
if ( !PC.VoteReplicationInfo.MapVoteEnabled() )
{
RemoveComponent(b_MapVote,True);
}
if ( !PC.VoteReplicationInfo.KickVoteEnabled() )
{
RemoveComponent(b_KickVote);
}
if ( !PC.VoteReplicationInfo.MatchSetupEnabled() )
{
RemoveComponent(b_MatchSetup);
}
}
else
{
RemoveComponent(b_MapVote);
RemoveComponent(b_KickVote);
RemoveComponent(b_MatchSetup);
}
RemapComponents();
}
function SetButtonPositions(Canvas C)
{
local int i, j, ButtonsPerRow, ButtonsLeftInRow, NumButtons;
local float Width, Height, Center, X, Y, YL, ButtonSpacing;
Width = b_Settings.ActualWidth();
Height = b_Settings.ActualHeight();
Center = ActualLeft() + (ActualWidth() / 2.0);
ButtonSpacing = Width * 0.05;
YL = Height * 1.2;
Y = b_Settings.ActualTop();
ButtonsPerRow = ActualWidth() / (Width + ButtonSpacing);
ButtonsLeftInRow = ButtonsPerRow;
for ( i = 0; i < Components.Length; i++)
{
if ( Components[i].bVisible && GUIButton(Components[i]) != none )
{
NumButtons++;
}
}
if ( NumButtons < ButtonsPerRow )
{
X = Center - (((Width * float(NumButtons)) + (ButtonSpacing * float(NumButtons - 1))) * 0.5);
}
else if ( ButtonsPerRow > 1 )
{
X = Center - (((Width * float(ButtonsPerRow)) + (ButtonSpacing * float(ButtonsPerRow - 1))) * 0.5);
}
else
{
X = Center - Width / 2.0;
}
for ( i = 0; i < Components.Length; i++)
{
if ( !Components[i].bVisible || GUIButton(Components[i]) == none )
{
continue;
}
Components[i].SetPosition( X, Y, Width, Height, true );
if ( --ButtonsLeftInRow > 0 )
{
X += Width + ButtonSpacing;
}
else
{
Y += YL;
for ( j = i + 1; j < Components.Length && ButtonsLeftInRow < ButtonsPerRow; j++)
{
if ( Components[i].bVisible && GUIButton(Components[i]) != none )
{
ButtonsLeftInRow++;
}
}
if ( ButtonsLeftInRow > 1 )
{
X = Center - (((Width * float(ButtonsLeftInRow)) + (ButtonSpacing * float(ButtonsLeftInRow - 1))) * 0.5);
}
else
{
X = Center - Width / 2.0;
}
}
}
}
// See if we already have this server in our favorites
function bool CurrentServerIsInFavorites()
{
local ExtendedConsole.ServerFavorite Fav;
local string address,portString;
// Get current network address
if ( PlayerOwner() == None )
return true;
address = PlayerOwner().GetServerNetworkAddress();
if( address == "" )
return true; // slightly hacky - dont want to add "none"!
// Parse text to find IP and possibly port number
if ( Divide(address, ":", Fav.IP, portstring) )
Fav.Port = int(portString);
else Fav.IP = address;
return class'KFConsole'.static.InFavorites(Fav);
}
function bool ButtonClicked(GUIComponent Sender)
{
local PlayerController PC;
PC = PlayerOwner();
if ( Sender == b_Settings )
{
// Settings
Controller.OpenMenu(Controller.GetSettingsPage());
}
else if ( Sender == b_Browser )
{
// Server browser
Controller.OpenMenu("KFGUI.KFServerBrowser");
}
else if ( Sender == b_Leave )
{
// Forfeit/Disconnect
PC.ConsoleCommand("DISCONNECT");
KFGUIController(Controller).ReturnToMainMenu();
}
else if ( Sender == b_Favs )
{
// Add this server to favorites
PC.ConsoleCommand( "ADDCURRENTTOFAVORITES" );
b_Favs.MenuStateChange(MSAT_Disabled);
}
else if ( Sender == b_Quit )
{
// Quit game
Controller.OpenMenu(Controller.GetQuitPage());
}
else if ( Sender == b_MapVote )
{
// Map voting
Controller.OpenMenu(Controller.MapVotingMenu);
}
else if ( Sender == b_KickVote )
{
// Kick voting
Controller.OpenMenu(Controller.KickVotingMenu);
}
else if ( Sender == b_MatchSetup )
{
// Match setup
Controller.OpenMenu(Controller.MatchSetupMenu);
}
else if ( Sender == b_Spec )
{
Controller.CloseMenu();
// Spectate/rejoin
if ( PC.PlayerReplicationInfo.bOnlySpectator )
PC.BecomeActivePlayer();
else PC.BecomeSpectator();
}
else if( Sender==b_Profile )
{
// Profile
Controller.OpenMenu(string(Class'SRProfilePage'));
}
return true;
}
function bool InternalOnPreDraw(Canvas C)
{
local GameReplicationInfo GRI;
local PlayerController PC;
GRI = GetGRI();
if ( GRI != none )
{
if ( bInit )
InitGRI();
SetButtonPositions(C);
PC = PlayerOwner();
if ( (PC.myHUD == None || !PC.myHUD.IsInCinematic()) && GRI != none && GRI.bMatchHasBegun && !PC.IsInState('GameEnded') )
EnableComponent(b_Spec);
else DisableComponent(b_Spec);
if( PC.PlayerReplicationInfo!=None && bOldSpectator!=PC.PlayerReplicationInfo.bOnlySpectator )
{
bOldSpectator = !bOldSpectator;
if ( bOldSpectator )
b_Spec.Caption = class'KFTab_MidGamePerks'.default.JoinGameButtonText;
else b_Spec.Caption = class'KFTab_MidGamePerks'.default.SpectateButtonText;
}
}
return false;
}
function RemoveMultiplayerTabs(GameInfo Game);
defaultproperties
{
Begin Object Class=GUIButton Name=SettingsButton
WinTop=0.900000
WinLeft=0.194420
WinWidth=0.147268
WinHeight=0.035000
TabOrder=0
bBoundToParent=True
bScaleToParent=True
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=SettingsButton.InternalOnKeyEvent
End Object
b_Settings=GUIButton'ServerPerks.SRInvasionLoginMenu.SettingsButton'
Begin Object Class=GUIButton Name=BrowserButton
bAutoSize=True
WinTop=0.850000
WinLeft=0.375000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=1
bBoundToParent=True
bScaleToParent=True
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=BrowserButton.InternalOnKeyEvent
End Object
b_Browser=GUIButton'ServerPerks.SRInvasionLoginMenu.BrowserButton'
Begin Object Class=GUIButton Name=QuitGameButton
bAutoSize=True
WinTop=0.870000
WinLeft=0.725000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=50
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=QuitGameButton.InternalOnKeyEvent
End Object
b_Quit=GUIButton'ServerPerks.SRInvasionLoginMenu.QuitGameButton'
Begin Object Class=GUIButton Name=FavoritesButton
bAutoSize=True
WinTop=0.870000
WinLeft=0.025000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=2
bBoundToParent=True
bScaleToParent=True
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=FavoritesButton.InternalOnKeyEvent
End Object
b_Favs=GUIButton'ServerPerks.SRInvasionLoginMenu.FavoritesButton'
Begin Object Class=GUIButton Name=LeaveMatchButton
bAutoSize=True
WinTop=0.870000
WinLeft=0.725000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=49
bBoundToParent=True
bScaleToParent=True
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=LeaveMatchButton.InternalOnKeyEvent
End Object
b_Leave=GUIButton'ServerPerks.SRInvasionLoginMenu.LeaveMatchButton'
Begin Object Class=GUIButton Name=MapVotingButton
bAutoSize=True
WinTop=0.890000
WinLeft=0.025000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=3
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=MapVotingButton.InternalOnKeyEvent
End Object
b_MapVote=GUIButton'ServerPerks.SRInvasionLoginMenu.MapVotingButton'
Begin Object Class=GUIButton Name=KickVotingButton
bAutoSize=True
WinTop=0.890000
WinLeft=0.375000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=4
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=KickVotingButton.InternalOnKeyEvent
End Object
b_KickVote=GUIButton'ServerPerks.SRInvasionLoginMenu.KickVotingButton'
Begin Object Class=GUIButton Name=MatchSetupButton
bAutoSize=True
WinTop=0.890000
WinLeft=0.725000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=5
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=MatchSetupButton.InternalOnKeyEvent
End Object
b_MatchSetup=GUIButton'ServerPerks.SRInvasionLoginMenu.MatchSetupButton'
Begin Object Class=GUIButton Name=SpectateButton
bAutoSize=True
WinTop=0.890000
WinLeft=0.725000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=6
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=SpectateButton.InternalOnKeyEvent
End Object
b_Spec=GUIButton'ServerPerks.SRInvasionLoginMenu.SpectateButton'
Begin Object Class=GUIButton Name=ProfileButton
Caption="Profile"
bAutoSize=True
WinTop=0.890000
WinLeft=0.725000
WinWidth=0.200000
WinHeight=0.050000
TabOrder=7
OnClick=SRInvasionLoginMenu.ButtonClicked
OnKeyEvent=ProfileButton.InternalOnKeyEvent
End Object
b_Profile=GUIButton'ServerPerks.SRInvasionLoginMenu.ProfileButton'
CurTabOrder=8
Panels(0)=(Caption="News",Hint="View server news")
Panels(4)=(Caption="Stats",Hint="View your current stats of this server")
OnPreDraw=SRInvasionLoginMenu.InternalOnPreDraw
}

View file

@ -0,0 +1,520 @@
//=============================================================================
// The trader menu's list with player's current inventory
//=============================================================================
class SRKFBuyMenuInvList extends KFBuyMenuInvList;
final function CopyAllBuyables()
{
local ClientPerkRepLink L;
local int i;
L = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if( L==None )
return;
for( i=0; i<MyBuyables.Length; ++i )
if( MyBuyables[i]!=None )
L.AllocatedObjects[L.AllocatedObjects.Length] = MyBuyables[i];
}
final function GUIBuyable AllocateEntry( ClientPerkRepLink L )
{
local GUIBuyable G;
if( L.AllocatedObjects.Length==0 )
return new Class'GUIBuyable';
G = L.AllocatedObjects[0];
L.ResetItem(G);
L.AllocatedObjects.Remove(0,1);
return G;
}
final function FreeBuyable( ClientPerkRepLink L, GUIBuyable B )
{
L.AllocatedObjects[L.AllocatedObjects.Length] = B;
}
event Closed(GUIComponent Sender, bool bCancelled)
{
CopyAllBuyables();
MyBuyables.Length = 0;
super.Closed(Sender, bCancelled);
}
function UpdateMyBuyables()
{
local GUIBuyable MyBuyable, KnifeBuyable, FragBuyable;
local array<GUIBuyable> SecTypes;
local Inventory CurInv;
local float CurAmmo, MaxAmmo;
local class<KFWeaponPickup> MyPickup,MyPrimaryPickup;
local int DualDivider,i;
local class<KFVeterancyTypes> KFV;
local ClientPerkRepLink KFLR;
local KFPlayerReplicationInfo PRI;
PRI = KFPlayerReplicationInfo(PlayerOwner().PlayerReplicationInfo);
KFLR = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if( KFLR==None || PRI==None )
return; // Hmmmm?
// Let's start with our current inventory
if ( PlayerOwner().Pawn.Inventory == none )
{
log("Inventory is none!");
return;
}
DualDivider = 1;
AutoFillCost = 0.00000;
// Clear the MyBuyables array
CopyAllBuyables();
MyBuyables.Length = 0;
KFV = PRI.ClientVeteranSkill;
if( KFV==None )
KFV = Class'KFVeterancyTypes';
// Fill the Buyables
for ( CurInv = PlayerOwner().Pawn.Inventory; CurInv != none; CurInv = CurInv.Inventory )
{
if ( KFWeapon(CurInv)==None || CurInv.IsA('Welder') || CurInv.IsA('Syringe') || CurInv.IsA('Dummy_JoggingWeapon') )
continue;
if ( CurInv.IsA('DualDeagle') || CurInv.IsA('Dual44Magnum') || CurInv.IsA('DualMK23Pistol') || KFWeapon(CurInv).DemoReplacement!=None )
DualDivider = 2;
else DualDivider = 1;
MyPickup = class<KFWeaponPickup>(CurInv.default.PickupClass);
KFWeapon(CurInv).GetAmmoCount(MaxAmmo, CurAmmo);
if ( KFWeapon(CurInv).bHasSecondaryAmmo )
MyPrimaryPickup = MyPickup.default.PrimaryWeaponPickup;
else MyPrimaryPickup = MyPickup;
MyBuyable = AllocateEntry(KFLR);
MyBuyable.ItemName = MyPickup.default.ItemShortName;
MyBuyable.ItemDescription = KFWeapon(CurInv).default.Description;
MyBuyable.ItemCategorie = "Melee"; // More dummy.
MyBuyable.ItemImage = KFWeapon(CurInv).default.TraderInfoTexture;
MyBuyable.ItemWeaponClass = KFWeapon(CurInv).class;
MyBuyable.ItemAmmoClass = KFWeapon(CurInv).default.FireModeClass[0].default.AmmoClass;
MyBuyable.ItemPickupClass = MyPrimaryPickup;
MyBuyable.ItemCost = (float(MyPickup.default.Cost) * KFV.static.GetCostScaling(PRI, MyPickup)) / DualDivider;
MyBuyable.ItemAmmoCost = MyPrimaryPickup.default.AmmoCost * KFV.static.GetAmmoCostScaling(PRI, MyPrimaryPickup)
* KFV.static.GetMagCapacityMod(PRI, KFWeapon(CurInv));
if( MyPickup==class'HuskGunPickup' )
MyBuyable.ItemFillAmmoCost = (int(((MaxAmmo - CurAmmo) * float(MyPrimaryPickup.default.AmmoCost)) / float(MyPrimaryPickup.default.BuyClipSize))) * KFV.static.GetAmmoCostScaling(PRI, MyPrimaryPickup);
else MyBuyable.ItemFillAmmoCost = (int(((MaxAmmo - CurAmmo) * float(MyPrimaryPickup.default.AmmoCost)) / float(KFWeapon(CurInv).default.MagCapacity))) * KFV.static.GetAmmoCostScaling(PRI, MyPrimaryPickup);
MyBuyable.ItemWeight = KFWeapon(CurInv).Weight;
MyBuyable.ItemPower = MyPickup.default.PowerValue;
MyBuyable.ItemRange = MyPickup.default.RangeValue;
MyBuyable.ItemSpeed = MyPickup.default.SpeedValue;
MyBuyable.ItemAmmoCurrent = CurAmmo;
MyBuyable.ItemAmmoMax = MaxAmmo;
MyBuyable.bMelee = (KFMeleeGun(CurInv)!=none || MyBuyable.ItemAmmoClass==None);
MyBuyable.bSaleList = false;
MyBuyable.ItemPerkIndex = MyPickup.default.CorrespondingPerkIndex;
if ( KFWeapon(CurInv) != none && KFWeapon(CurInv).SellValue != -1 )
MyBuyable.ItemSellValue = KFWeapon(CurInv).SellValue;
else MyBuyable.ItemSellValue = MyBuyable.ItemCost * 0.75;
if ( !MyBuyable.bMelee && int(MaxAmmo)>int(CurAmmo) )
AutoFillCost += MyBuyable.ItemFillAmmoCost;
if ( CurInv.IsA('Knife') )
{
MyBuyable.bSellable = false;
KnifeBuyable = MyBuyable;
}
else if ( CurInv.IsA('Frag') )
{
MyBuyable.bSellable = false;
FragBuyable = MyBuyable;
}
else
{
MyBuyable.bSellable = !KFWeapon(CurInv).default.bKFNeverThrow;
MyBuyables.Insert(0,1);
MyBuyables[0] = MyBuyable;
}
if ( !KFWeapon(CurInv).bHasSecondaryAmmo )
continue;
// Add secondary ammo.
KFWeapon(CurInv).GetSecondaryAmmoCount(MaxAmmo, CurAmmo);
MyBuyable = AllocateEntry(KFLR);
MyBuyable.ItemName = MyPickup.default.SecondaryAmmoShortName;
MyBuyable.ItemDescription = KFWeapon(CurInv).default.Description;
MyBuyable.ItemCategorie = "Melee";
MyBuyable.ItemImage = KFWeapon(CurInv).default.TraderInfoTexture;
MyBuyable.ItemWeaponClass = KFWeapon(CurInv).class;
MyBuyable.ItemAmmoClass = KFWeapon(CurInv).default.FireModeClass[1].default.AmmoClass;
MyBuyable.ItemPickupClass = MyPickup;
MyBuyable.ItemCost = (float(MyPickup.default.Cost) * KFV.static.GetCostScaling(PRI, MyPickup)) / DualDivider;
MyBuyable.ItemAmmoCost = MyPickup.default.AmmoCost * KFV.static.GetAmmoCostScaling(PRI, MyPickup) * KFV.static.GetMagCapacityMod(PRI, KFWeapon(CurInv));
MyBuyable.ItemFillAmmoCost = (int(((MaxAmmo - CurAmmo) * float(MyPickup.default.AmmoCost)) /* Secondary Mags always have a Mag Capacity of 1? / float(KFWeapon(CurInv).default.MagCapacity)*/)) * KFV.static.GetAmmoCostScaling(PRI, MyPickup);
MyBuyable.ItemWeight = KFWeapon(CurInv).Weight;
MyBuyable.ItemPower = MyPickup.default.PowerValue;
MyBuyable.ItemRange = MyPickup.default.RangeValue;
MyBuyable.ItemSpeed = MyPickup.default.SpeedValue;
MyBuyable.ItemAmmoCurrent = CurAmmo;
MyBuyable.ItemAmmoMax = MaxAmmo;
MyBuyable.bMelee = (KFMeleeGun(CurInv) != none);
MyBuyable.bSaleList = false;
MyBuyable.ItemPerkIndex = MyPickup.default.CorrespondingPerkIndex;
MyBuyable.bSellable = !KFWeapon(CurInv).default.bKFNeverThrow;
if ( KFWeapon(CurInv) != none && KFWeapon(CurInv).SellValue != -1 )
MyBuyable.ItemSellValue = KFWeapon(CurInv).SellValue;
else MyBuyable.ItemSellValue = MyBuyable.ItemCost * 0.75;
if ( !MyBuyable.bMelee && int(MaxAmmo) > int(CurAmmo))
AutoFillCost += MyBuyable.ItemFillAmmoCost;
SecTypes[SecTypes.Length] = MyBuyable;
}
MyBuyable = AllocateEntry(KFLR);
MyBuyable.ItemName = class'BuyableVest'.default.ItemName;
MyBuyable.ItemDescription = class'BuyableVest'.default.ItemDescription;
MyBuyable.ItemCategorie = "";
MyBuyable.ItemImage = class'BuyableVest'.default.ItemImage;
MyBuyable.ItemAmmoCurrent = PlayerOwner().Pawn.ShieldStrength;
MyBuyable.ItemAmmoMax = 100;
MyBuyable.ItemCost = int(class'BuyableVest'.default.ItemCost * KFV.static.GetCostScaling(PRI, class'Vest'));
MyBuyable.ItemAmmoCost = MyBuyable.ItemCost / 100;
MyBuyable.ItemFillAmmoCost = int((100.0 - MyBuyable.ItemAmmoCurrent) * MyBuyable.ItemAmmoCost);
MyBuyable.bIsVest = true;
MyBuyable.bMelee = false;
MyBuyable.bSaleList = false;
MyBuyable.bSellable = false;
MyBuyable.ItemPerkIndex = class'BuyableVest'.default.CorrespondingPerkIndex;
if( MyBuyables.Length<=(7-SecTypes.Length) )
{
MyBuyables.Length = 11;
for( i=(SecTypes.Length-1); i>=0; --i )
MyBuyables[7-i] = SecTypes[i];
MyBuyables[8] = KnifeBuyable;
MyBuyables[9] = FragBuyable;
MyBuyables[10] = MyBuyable;
}
else
{
MyBuyables[MyBuyables.Length] = none;
for( i=(SecTypes.Length-1); i>=0; --i )
MyBuyables[MyBuyables.Length] = SecTypes[i];
MyBuyables[MyBuyables.Length] = KnifeBuyable;
MyBuyables[MyBuyables.Length] = FragBuyable;
MyBuyables[MyBuyables.Length] = MyBuyable;
}
//Now Update the list
UpdateList();
}
function UpdateList()
{
local int i;
local ClientPerkRepLink KFLR;
KFLR = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( MyBuyables.Length < 1 )
{
bNeedsUpdate = true;
return;
}
// Clear the arrays
NameStrings.Remove(0, NameStrings.Length);
AmmoStrings.Remove(0, AmmoStrings.Length);
ClipPriceStrings.Remove(0, ClipPriceStrings.Length);
FillPriceStrings.Remove(0, FillPriceStrings.Length);
PerkTextures.Remove(0, PerkTextures.Length);
// Update the ItemCount and select the first item
ItemCount = MyBuyables.Length;
// Update the players inventory list
for ( i = 0; i < ItemCount; i++ )
{
if ( MyBuyables[i] == none )
continue;
NameStrings[i] = MyBuyables[i].ItemName;
if ( !MyBuyables[i].bIsVest )
{
AmmoStrings[i] = int(MyBuyables[i].ItemAmmoCurrent)$"/"$int(MyBuyables[i].ItemAmmoMax);
if ( MyBuyables[i].ItemAmmoCurrent < MyBuyables[i].ItemAmmoMax )
{
if ( MyBuyables[i].ItemAmmoCost > MyBuyables[i].ItemFillAmmoCost )
{
ClipPriceStrings[i] = "£" @ int(MyBuyables[i].ItemFillAmmoCost);
}
else
{
ClipPriceStrings[i] = "£" @ int(MyBuyables[i].ItemAmmoCost);
}
}
else
{
ClipPriceStrings[i] = "£ 0";
}
FillPriceStrings[i] = "£" @ int(MyBuyables[i].ItemFillAmmoCost);
}
else
{
AmmoStrings[i] = int((MyBuyables[i].ItemAmmoCurrent / MyBuyables[i].ItemAmmoMax) * 100.0)$"%";
if ( MyBuyables[i].ItemAmmoCurrent == 0 )
{
FillPriceStrings[i] = BuyString @ ": £" @ int(MyBuyables[i].ItemFillAmmoCost);
}
else if ( MyBuyables[i].ItemAmmoCurrent == 100 )
{
FillPriceStrings[i] = PurchasedString;
}
else
{
FillPriceStrings[i] = RepairString @ ": £" @ int(MyBuyables[i].ItemFillAmmoCost);
}
}
if( KFLR!=None && KFLR.ShopPerkIcons.Length>MyBuyables[i].ItemPerkIndex )
PerkTextures[i] = Texture(KFLR.ShopPerkIcons[MyBuyables[i].ItemPerkIndex]);
}
if ( bNotify )
CheckLinkedObjects(Self);
if ( MyScrollBar != none )
MyScrollBar.AlignThumb();
}
function DrawInvItem(Canvas Canvas, int CurIndex, float X, float Y, float Width, float Height, bool bSelected, bool bPending)
{
local float IconBGSize, ItemBGWidth, AmmoBGWidth, ClipButtonWidth, FillButtonWidth;
local float TempX, TempY;
local float StringHeight, StringWidth;
OnClickSound=CS_Click;
// Initialize the Canvas
Canvas.Style = 1;
// Canvas.Font = class'ROHUD'.Static.GetSmallMenuFont(Canvas);
Canvas.SetDrawColor(255, 255, 255, 255);
if ( MyBuyables[CurIndex]==None )
{
if( MyBuyables.Length==(CurIndex+1) || MyBuyables[CurIndex+1]==None )
return;
Canvas.SetPos(X + EquipmentBGXOffset, Y + Height - EquipmentBGYOffset - EquipmentBGHeightScale * Height);
Canvas.DrawTileStretched(AmmoBackground, EquipmentBGWidthScale * Width, EquipmentBGHeightScale * Height);
Canvas.SetDrawColor(175, 176, 158, 255);
Canvas.StrLen(EquipmentString, StringWidth, StringHeight);
Canvas.SetPos(X + EquipmentBGXOffset + ((EquipmentBGWidthScale * Width - StringWidth) / 2.0), Y + Height - EquipmentBGYOffset - EquipmentBGHeightScale * Height + ((EquipmentBGHeightScale * Height - StringHeight) / 2.0));
Canvas.DrawText(EquipmentString);
}
else
{
// Calculate Widths for all components
IconBGSize = Height;
ItemBGWidth = (Width * ItemBGWidthScale) - IconBGSize;
AmmoBGWidth = Width * AmmoBGWidthScale;
if ( !MyBuyables[CurIndex].bIsVest )
{
FillButtonWidth = ((1.0 - ItemBGWidthScale - AmmoBGWidthScale) * Width) - ButtonSpacing;
ClipButtonWidth = FillButtonWidth * ClipButtonWidthScale;
FillButtonWidth -= ClipButtonWidth;
}
else
{
FillButtonWidth = ((1.0 - ItemBGWidthScale - AmmoBGWidthScale) * Width);
}
// Offset for the Background
TempX = X;
TempY = Y;
// Draw Item Background
Canvas.SetPos(TempX, TempY);
if ( bSelected )
{
Canvas.DrawTileStretched(SelectedItemBackgroundLeft, IconBGSize, IconBGSize);
Canvas.SetPos(TempX + 4, TempY + 4);
Canvas.DrawTile(PerkTextures[CurIndex], IconBGSize - 8, IconBGSize - 8, 0, 0, 256, 256);
TempX += IconBGSize;
Canvas.SetPos(TempX, TempY + ItemBGYOffset);
Canvas.DrawTileStretched(SelectedItemBackgroundRight, ItemBGWidth, IconBGSize - (2.0 * ItemBGYOffset));
}
else
{
Canvas.DrawTileStretched(ItemBackgroundLeft, IconBGSize, IconBGSize);
Canvas.SetPos(TempX + 4, TempY + 4);
Canvas.DrawTile(PerkTextures[CurIndex], IconBGSize - 8, IconBGSize - 8, 0, 0, 256, 256);
TempX += IconBGSize;
Canvas.SetPos(TempX, TempY + ItemBGYOffset);
Canvas.DrawTileStretched(ItemBackgroundRight, ItemBGWidth, IconBGSize - (2.0 * ItemBGYOffset));
}
// Select Text color
if ( CurIndex == MouseOverIndex && MouseOverXIndex == 0 )
Canvas.SetDrawColor(255, 255, 255, 255);
else Canvas.SetDrawColor(0, 0, 0, 255);
// Draw the item's name
Canvas.StrLen(NameStrings[CurIndex], StringWidth, StringHeight);
Canvas.SetPos(TempX + ItemNameSpacing, Y + ((Height - StringHeight) / 2.0));
Canvas.DrawText(NameStrings[CurIndex]);
// Draw the item's ammo status if it is not a melee weapon
if ( !MyBuyables[CurIndex].bMelee )
{
TempX += ItemBGWidth + AmmoSpacing;
Canvas.SetDrawColor(255, 255, 255, 255);
Canvas.SetPos(TempX, TempY + ((Height - AmmoBGHeightScale * Height) / 2.0));
Canvas.DrawTileStretched(AmmoBackground, AmmoBGWidth, AmmoBGHeightScale * Height);
Canvas.SetDrawColor(175, 176, 158, 255);
Canvas.StrLen(AmmoStrings[CurIndex], StringWidth, StringHeight);
Canvas.SetPos(TempX + ((AmmoBGWidth - StringWidth) / 2.0), TempY + ((Height - StringHeight) / 2.0));
Canvas.DrawText(AmmoStrings[CurIndex]);
TempX += AmmoBGWidth + AmmoSpacing;
Canvas.SetDrawColor(255, 255, 255, 255);
Canvas.SetPos(TempX, TempY + ((Height - ButtonBGHeightScale * Height) / 2.0));
if ( !MyBuyables[CurIndex].bIsVest )
{
if ( MyBuyables[CurIndex].ItemAmmoCurrent >= MyBuyables[CurIndex].ItemAmmoMax ||
(PlayerOwner().PlayerReplicationInfo.Score < MyBuyables[CurIndex].ItemFillAmmoCost && PlayerOwner().PlayerReplicationInfo.Score < MyBuyables[CurIndex].ItemAmmoCost) )
{
Canvas.DrawTileStretched(DisabledButtonBackground, ClipButtonWidth, ButtonBGHeightScale * Height);
Canvas.SetDrawColor(0, 0, 0, 255);
}
else if ( CurIndex == MouseOverIndex && MouseOverXIndex == 1 )
{
Canvas.DrawTileStretched(HoverButtonBackground, ClipButtonWidth, ButtonBGHeightScale * Height);
}
else
{
Canvas.DrawTileStretched(ButtonBackground, ClipButtonWidth, ButtonBGHeightScale * Height);
Canvas.SetDrawColor(0, 0, 0, 255);
}
Canvas.StrLen(ClipPriceStrings[CurIndex], StringWidth, StringHeight);
Canvas.SetPos(TempX + ((ClipButtonWidth - StringWidth) / 2.0), TempY + ((Height - StringHeight) / 2.0));
Canvas.DrawText(ClipPriceStrings[CurIndex]);
TempX += ClipButtonWidth + ButtonSpacing;
Canvas.SetDrawColor(255, 255, 255, 255);
Canvas.SetPos(TempX, TempY + ((Height - ButtonBGHeightScale * Height) / 2.0));
if ( MyBuyables[CurIndex].ItemAmmoCurrent >= MyBuyables[CurIndex].ItemAmmoMax ||
(PlayerOwner().PlayerReplicationInfo.Score < MyBuyables[CurIndex].ItemFillAmmoCost && PlayerOwner().PlayerReplicationInfo.Score < MyBuyables[CurIndex].ItemAmmoCost) )
{
Canvas.DrawTileStretched(DisabledButtonBackground, FillButtonWidth, ButtonBGHeightScale * Height);
Canvas.SetDrawColor(0, 0, 0, 255);
}
else if ( CurIndex == MouseOverIndex && MouseOverXIndex == 2 )
{
Canvas.DrawTileStretched(HoverButtonBackground, FillButtonWidth, ButtonBGHeightScale * Height);
}
else
{
Canvas.DrawTileStretched(ButtonBackground, FillButtonWidth, ButtonBGHeightScale * Height);
Canvas.SetDrawColor(0, 0, 0, 255);
}
}
else
{
if ( (PlayerOwner().Pawn.ShieldStrength > 0 && PlayerOwner().PlayerReplicationInfo.Score < MyBuyables[CurIndex].ItemAmmoCost) ||
(PlayerOwner().Pawn.ShieldStrength <= 0 && PlayerOwner().PlayerReplicationInfo.Score < MyBuyables[CurIndex].ItemCost) ||
MyBuyables[CurIndex].ItemAmmoCurrent >= MyBuyables[CurIndex].ItemAmmoMax )
{
Canvas.DrawTileStretched(DisabledButtonBackground, FillButtonWidth, ButtonBGHeightScale * Height);
Canvas.SetDrawColor(0, 0, 0, 255);
}
else if ( CurIndex == MouseOverIndex && MouseOverXIndex >= 1 )
{
Canvas.DrawTileStretched(HoverButtonBackground, FillButtonWidth, ButtonBGHeightScale * Height);
}
else
{
Canvas.DrawTileStretched(ButtonBackground, FillButtonWidth, ButtonBGHeightScale * Height);
Canvas.SetDrawColor(0, 0, 0, 255);
}
}
Canvas.StrLen(FillPriceStrings[CurIndex], StringWidth, StringHeight);
Canvas.SetPos(TempX + ((FillButtonWidth - StringWidth) / 2.0), TempY + ((Height - StringHeight) / 2.0));
Canvas.DrawText(FillPriceStrings[CurIndex]);
}
Canvas.SetDrawColor(255, 255, 255, 255);
}
}
function bool InternalOnClick(GUIComponent Sender)
{
local int NewIndex;
local float RelativeMouseX;
if ( IsInClientBounds() && MyBuyables[NewIndex] != none )
{
// Figure out which Item we're clicking on
NewIndex = CalculateIndex();
RelativeMouseX = Controller.MouseX - ClientBounds[0];
if ( RelativeMouseX < ActualWidth() * ItemBGWidthScale )
{
SetIndex(NewIndex);
MouseOverXIndex = 0;
return true;
}
else
{
RelativeMouseX -= ActualWidth() * (ItemBGWidthScale + AmmoBGWidthScale);
if ( RelativeMouseX > 0 )
{
if ( MyBuyables[NewIndex].bIsVest )
{
if ( (PlayerOwner().Pawn.ShieldStrength > 0 && PlayerOwner().PlayerReplicationInfo.Score >= MyBuyables[NewIndex].ItemAmmoCost) || PlayerOwner().PlayerReplicationInfo.Score >= MyBuyables[NewIndex].ItemCost )
{
OnBuyVestClick();
}
}
else if ( RelativeMouseX < ActualWidth() * (1.0 - ItemBGWidthScale - AmmoBGWidthScale) * ClipButtonWidthScale )
{
// Buy Clip
OnBuyClipClick(MyBuyables[NewIndex]);
}
else
{
// Fill Ammo
OnFillAmmoClick(MyBuyables[NewIndex]);
}
}
}
}
return false;
}
defaultproperties
{
}

View file

@ -0,0 +1,22 @@
class SRKFBuyMenuInvListBox extends KFBuyMenuInvListBox;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
DefaultListClass = string(Class'SRKFBuyMenuInvList');
Super.InitComponent(MyController,MyOwner);
}
final function GUIBuyable FindMatchingBuyable( Class<Actor> A )
{
local bool bArmor;
local int i;
bArmor = (A==Class'Vest');
for( i=0; i<List.MyBuyables.Length; ++i )
if( List.MyBuyables[i]!=None && (List.MyBuyables[i].ItemWeaponClass==A || (bArmor && List.MyBuyables[i].bIsVest)) )
return List.MyBuyables[i];
return None;
}
defaultproperties
{
}

View file

@ -0,0 +1,136 @@
//=============================================================================
// Quick Perk Select Menu for the trader
//=============================================================================
class SRKFQuickPerkSelect extends KFQuickPerkSelect;
event InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local ClientPerkRepLink S;
Super(GUIMultiComponent).InitComponent(MyController, MyOwner);
if ( PlayerOwner() != none )
{
S = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( S!=none )
CheckPerksX(S);
}
}
function bool MyOnDraw(Canvas C)
{
local int i, j;
local ClientPerkRepLink S;
local Material M,SM;
super(GUIMultiComponent).OnDraw(C);
C.SetDrawColor(255, 255, 255, 255);
// make em square
if ( !bResized )
{
ResizeIcons(C);
}
// Current perk background
C.SetPos(WinLeft * C.ClipX , WinTop * C.ClipY);
C.DrawTileScaled(CurPerkBack, (WinHeight * C.ClipY) / CurPerkBack.USize, (WinHeight * C.ClipY) / CurPerkBack.USize);
S = Class'ClientPerkRepLink'.Static.FindStats(C.Viewport.Actor);
if( S!=None )
{
// check if the current perk has changed recently
CheckPerksX(S);
j = 0;
// Draw the available perks
for ( i=0; i<MaxPerks; i++ )
{
if ( i != CurPerk )
{
S.CachePerks[i].PerkClass.Static.PreDrawPerk(C,Max(S.CachePerks[i].CurrentLevel,1)-1,M,SM);
PerkSelectIcons[j].Image = M;
PerkSelectIcons[j].Index = i;
PerkSelectIcons[j].ImageColor = C.DrawColor;
PerkSelectIcons[j].ImageColor.A = 255;
j++;
}
}
for( i=j; i<ArrayCount(PerkSelectIcons); ++i )
{
PerkSelectIcons[i].Image = None;
PerkSelectIcons[i].Index = -1;
}
// Draw current perk
if( CurPerk!=255 )
DrawCurrentPerkX(S, C, CurPerk);
}
return false;
}
function bool InternalOnClick(GUIComponent Sender)
{
local ClientPerkRepLink S;
if ( Sender.IsA('KFIndexedGUIImage') && KFIndexedGUIImage(Sender).Index>=0 )
{
S = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( S!=None )
S.ServerSelectPerk(S.CachePerks[KFIndexedGUIImage(Sender).Index].PerkClass);
bPerkChange = true;
}
return false;
}
function DrawCurrentPerkX( ClientPerkRepLink S, Canvas C, Int PerkIndex)
{
local Class<SRVeterancyTypes> V;
local Material M,SM;
V = S.CachePerks[PerkIndex].PerkClass;
C.SetPos(WinLeft * C.ClipX , WinTop * C.ClipY);
V.Static.PreDrawPerk(C,Max(S.CachePerks[PerkIndex].CurrentLevel,1)-1,M,SM);
if( M!=None )
C.DrawTileScaled(M, (WinHeight * C.ClipY) / M.MaterialUSize(), (WinHeight * C.ClipY) / M.MaterialVSize());
}
function CheckPerksX( ClientPerkRepLink S )
{
local int i;
local KFPlayerReplicationInfo PRI;
// Grab the Player Controller for later use
PRI = KFPlayerReplicationInfo(PlayerOwner().PlayerReplicationInfo);
// Hold onto our reference
if( S==None )
return;
if( S.CachePerks.Length==0 )
{
S.ServerRequestPerks();
return;
}
// Update the ItemCount and select the first item
MaxPerks = Min(S.CachePerks.Length,ArrayCount(PerkSelectIcons));
CurPerk = 255;
for( i=0; i<S.CachePerks.Length; i++ )
{
if ( PRI!=none && S.CachePerks[i].PerkClass==PRI.ClientVeteranSkill )
{
CurPerk = i;
break;
}
}
bPerkChange = false;
}
defaultproperties
{
}

View file

@ -0,0 +1,274 @@
//=============================================================================
// The actual trader menu
//=============================================================================
class SRKFTab_BuyMenu extends KFTab_BuyMenu;
var Class<Pickup> SelectedItem;
var() localized string ArchivementGetInfo;
struct FIDPair
{
var int ID;
var string Name;
};
var array<FIDPair> DLCMap;
var int InventoryHash,iFrameCounter;
var class<KFVeterancyTypes> OldPerkClass;
function Timer()
{
local int i;
++iFrameCounter;
i = GetInventoryHash();
if( i!=InventoryHash )
{
InventoryHash = i;
MoneyLabel.Caption = MoneyCaption $ int(PlayerOwner().PlayerReplicationInfo.Score);
UpdateAll();
}
}
function UpdateCheck();
final function int GetInventoryHash() // Get Inventory ID hash to check for changes.
{
local int i,n;
local Inventory Inv;
local KFWeapon W;
local PlayerController PC;
local class<KFVeterancyTypes> V;
PC = PlayerOwner();
if( PC.Pawn==None || KFPlayerReplicationInfo(PC.PlayerReplicationInfo)==None )
return (iFrameCounter>>3);
// Force update hash if perk is changed.
if( KFPlayerReplicationInfo(PC.PlayerReplicationInfo)!=None )
V = KFPlayerReplicationInfo(PC.PlayerReplicationInfo).ClientVeteranSkill;
if( OldPerkClass!=V )
{
OldPerkClass = V;
InventoryHash = 0;
}
i = (int(PC.PlayerReplicationInfo.Score) << 6) ^ (iFrameCounter>>7) ^ int(PC.Pawn.ShieldStrength);
for( Inv=PC.Pawn.Inventory; Inv!=None; Inv=Inv.Inventory )
{
++n;
W = KFWeapon(Inv);
if( W!=None )
{
n += 15;
i = i ^ (int(W.Weight)>>1) ^ (W.SleeveNum<<3) ^ (int(W.PlayerViewOffset.X)<<4) ^ (W.AmmoAmount(0)<<16);
}
}
return (i ^ n);
}
final function RefreshSelection()
{
if( SaleSelect.List.Index==-1 )
{
if( InvSelect.List.Index!=-1 )
TheBuyable = InvSelect.GetSelectedBuyable();
else TheBuyable = None;
}
else TheBuyable = SaleSelect.GetSelectedBuyable();
}
function OnAnychange()
{
RefreshSelection();
Super.OnAnychange();
}
function bool InternalOnClick(GUIComponent Sender)
{
RefreshSelection();
return Super.InternalOnClick(Sender);
}
function UpdateAll()
{
InvSelect.List.UpdateMyBuyables();
SaleSelect.List.UpdateForSaleBuyables();
RefreshSelection();
GetUpdatedBuyable();
UpdatePanel();
}
function UpdateBuySellButtons()
{
RefreshSelection();
if ( InvSelect.List.Index==-1 || TheBuyable==None || !TheBuyable.bSellable )
SaleButton.DisableMe();
else SaleButton.EnableMe();
if ( SaleSelect.List.Index==-1 || TheBuyable==None || SaleSelect.List.CanBuys[SaleSelect.List.Index]!=1 )
PurchaseButton.DisableMe();
else PurchaseButton.EnableMe();
}
function GetUpdatedBuyable(optional bool bSetInvIndex)
{
InvSelect.List.UpdateMyBuyables();
RefreshSelection();
}
function UpdateAutoFillAmmo()
{
Super.UpdateAutoFillAmmo();
RefreshSelection();
}
function SaleChange(GUIComponent Sender)
{
InvSelect.List.Index = -1;
TheBuyable = SaleSelect.GetSelectedBuyable();
if( TheBuyable==None ) // Selected category.
{
GUIBuyMenu(OwnerPage()).WeightBar.NewBoxes = 0;
if( SaleSelect.List.Index>=0 && SaleSelect.List.CanBuys[SaleSelect.List.Index]>1 )
{
SRBuyMenuSaleList(SaleSelect.List).SetCategoryNum(SaleSelect.List.CanBuys[SaleSelect.List.Index]-3);
}
}
else GUIBuyMenu(OwnerPage()).WeightBar.NewBoxes = TheBuyable.ItemWeight;
OnAnychange();
}
function bool SaleDblClick(GUIComponent Sender)
{
InvSelect.List.Index = -1;
TheBuyable = SaleSelect.GetSelectedBuyable();
if( TheBuyable==None ) // Selected category.
{
GUIBuyMenu(OwnerPage()).WeightBar.NewBoxes = 0;
}
else
{
GUIBuyMenu(OwnerPage()).WeightBar.NewBoxes = TheBuyable.ItemWeight;
if ( SaleSelect.List.CanBuys[SaleSelect.List.Index]==1 )
{
DoBuy();
TheBuyable = none;
}
}
OnAnychange();
return false;
}
final function string InitNewDLCName( int ID )
{
local int i;
local SRSteamStatsGet ST;
local string S;
// Grab DLC name through an ugly hack.
Class'SRSteamStatsGet'.Default.bNoInit = true;
ST = PlayerOwner().Spawn(Class'SRSteamStatsGet');
Class'SRSteamStatsGet'.Default.bNoInit = false;
S = ST.GetWeaponDLCPackName(ID);
ST.Destroy();
if( S=="" ) // Misc, unnamed.
S = "Unknown";
// Cache result.
i = DLCMap.Length;
DLCMap.Length = i+1;
DLCMap[i].ID = ID;
DLCMap[i].Name = S;
return S;
}
final function string GetDLCName( int ID )
{
local int i;
// See if already cached.
for( i=0; i<DLCMap.Length; ++i )
if( DLCMap[i].ID==ID )
return DLCMap[i].Name;
// Cache new one.
return InitNewDLCName(ID);
}
function SetInfoText()
{
local string TempString;
if ( TheBuyable == none && !bDidBuyableUpdate )
{
InfoScrollText.SetContent(InfoText[0]);
bDidBuyableUpdate = true;
return;
}
if ( TheBuyable != none && OldPickupClass != TheBuyable.ItemPickupClass )
{
// Unowned Weapon DLC
if( TheBuyable.bSaleList && TheBuyable.ItemAmmoCurrent>0 )
{
if( TheBuyable.ItemAmmoCurrent==1 )
InfoScrollText.SetContent(Repl(InfoText[4], "%1", GetDLCName(TheBuyable.ItemWeaponClass.Default.AppID)));
else if( TheBuyable.ItemAmmoCurrent==2 )
InfoScrollText.SetContent(Repl(ArchivementGetInfo, "%1", Class'SRSteamStatsGet'.Default.Achievements[TheBuyable.ItemWeaponClass.Default.UnlockedByAchievement].DisplayName));
else InfoScrollText.SetContent(Mid(TheBuyable.ItemCategorie,InStr(TheBuyable.ItemCategorie,":")+1));
}
// Too expensive
else if ( TheBuyable.ItemCost > PlayerOwner().PlayerReplicationInfo.Score && TheBuyable.bSaleList )
{
InfoScrollText.SetContent(InfoText[2]);
}
// Too heavy
else if ( TheBuyable.ItemWeight + KFHumanPawn(PlayerOwner().Pawn).CurrentWeight > KFHumanPawn(PlayerOwner().Pawn).MaxCarryWeight && TheBuyable.bSaleList )
{
TempString = Repl(Infotext[1], "%1", int(TheBuyable.ItemWeight));
TempString = Repl(TempString, "%2", int(KFHumanPawn(PlayerOwner().Pawn).MaxCarryWeight - KFHumanPawn(PlayerOwner().Pawn).CurrentWeight));
InfoScrollText.SetContent(TempString);
}
// default
else if( TheBuyable.ItemWeaponClass!=None )
InfoScrollText.SetContent(TheBuyable.ItemWeaponClass.Default.Description);
else InfoScrollText.SetContent(InfoText[0]);
bDidBuyableUpdate = false;
OldPickupClass = TheBuyable.ItemPickupClass;
}
}
defaultproperties
{
ArchivementGetInfo="This weapon requires archivement '%1' to be unlocked."
DLCMap(0)=(id=258751,Name="IJC Weapons 3")
DLCMap(1)=(id=210944,Name="Golden Weapons 2")
DLCMap(2)=(id=210938,Name="Golden Weapons")
DLCMap(3)=(id=210934,Name="IJC Weapons")
DLCMap(4)=(id=210943,Name="IJC Weapons 2")
DLCMap(5)=(id=258752,Name="Camo Weapons")
DLCMap(6)=(id=309991,Name="Neon Weapons")
Begin Object Class=SRKFBuyMenuInvListBox Name=InventoryBox
OnCreateComponent=InventoryBox.InternalOnCreateComponent
WinTop=0.070841
WinLeft=0.000108
WinWidth=0.328204
WinHeight=0.521856
End Object
InvSelect=SRKFBuyMenuInvListBox'ServerPerks.SRKFTab_BuyMenu.InventoryBox'
Begin Object Class=SRGUIBuyWeaponInfoPanel Name=ItemInf
WinTop=0.193730
WinLeft=0.332571
WinWidth=0.333947
WinHeight=0.489407
End Object
ItemInfo=SRGUIBuyWeaponInfoPanel'ServerPerks.SRKFTab_BuyMenu.ItemInf'
Begin Object Class=SRBuyMenuSaleListBox Name=SaleBox
OnCreateComponent=SaleBox.InternalOnCreateComponent
WinTop=0.064312
WinLeft=0.672632
WinWidth=0.325857
WinHeight=0.674039
End Object
SaleSelect=SRBuyMenuSaleListBox'ServerPerks.SRKFTab_BuyMenu.SaleBox'
InfoText(4)="This weapon requires '%1' DLC pack."
}

View file

@ -0,0 +1,77 @@
//-----------------------------------------------------------
//
//-----------------------------------------------------------
class SRKFTab_Perks extends KFTab_Perks;
function ShowPanel(bool bShow)
{
super(UT2K4TabPanel).ShowPanel(bShow);
if ( bShow )
{
if ( Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner())!=None )
{
// Initialize the List
lb_PerkSelect.List.InitList(None);
lb_PerkProgress.List.InitList();
}
l_ChangePerkOncePerWave.SetVisibility(false);
}
}
function OnPerkSelected(GUIComponent Sender)
{
local ClientPerkRepLink ST;
local byte Idx;
local string S;
ST = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( ST==None || ST.CachePerks.Length==0 )
{
if( ST!=None )
ST.ServerRequestPerks();
lb_PerkEffects.SetContent("Please wait while your client is loading the perks...");
}
else
{
Idx = lb_PerkSelect.GetIndex();
if( ST.CachePerks[Idx].CurrentLevel==0 )
S = ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(0,1);
else if( ST.CachePerks[Idx].CurrentLevel==ST.MaximumLevel )
S = ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel-1,1);
else S = ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel-1,1)$Class'SRTab_MidGamePerks'.Default.NextInfoStr$ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel,1);
lb_PerkEffects.SetContent(S);
lb_PerkProgress.List.PerkChanged(KFStatsAndAchievements, Idx);
}
}
function bool OnSaveButtonClicked(GUIComponent Sender)
{
local ClientPerkRepLink ST;
ST = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( ST!=None && lb_PerkSelect.GetIndex()>=0 )
ST.ServerSelectPerk(ST.CachePerks[lb_PerkSelect.GetIndex()].PerkClass);
return true;
}
defaultproperties
{
Begin Object Class=SRPerkSelectListBox Name=PerkSelectList
OnCreateComponent=PerkSelectList.InternalOnCreateComponent
WinTop=0.091627
WinLeft=0.029240
WinWidth=0.437166
WinHeight=0.742836
End Object
lb_PerkSelect=SRPerkSelectListBox'ServerPerks.SRKFTab_Perks.PerkSelectList'
Begin Object Class=SRPerkProgressListBox Name=PerkProgressList
OnCreateComponent=PerkProgressList.InternalOnCreateComponent
WinTop=0.476850
WinLeft=0.499269
WinWidth=0.463858
WinHeight=0.341256
End Object
lb_PerkProgress=SRPerkProgressListBox'ServerPerks.SRKFTab_Perks.PerkProgressList'
}

View file

@ -0,0 +1,48 @@
Class SRLevelCleanup extends Interaction;
var string SwitchToURL;
function NotifyLevelChange()
{
local int i;
// Make sure GUI controller leaves no menus referenced.
GUIController(ViewportOwner.GUIController).ResetFocus();
GUIController(ViewportOwner.GUIController).FocusedControl = None;
for( i=(ViewportOwner.LocalInteractions.Length-1); i>=0; --i )
if( ViewportOwner.LocalInteractions[i]==Self )
ViewportOwner.LocalInteractions.Remove(i,1);
if( SwitchToURL!="" )
ViewportOwner.Console.DelayedConsoleCommand("OPEN "$SwitchToURL); // Switch server.
else ViewportOwner.Console.DelayedConsoleCommand("OBJ GARBAGE"); // Ensure to cleanup everything releated to this mod.
}
static final function AddSafeCleanup( PlayerController PC, optional string NextURL )
{
local int i;
local SRLevelCleanup C;
if( NextURL!="" )
PC.Player.Console.DelayedConsoleCommand("DISCONNECT");
for( i=(PC.Player.LocalInteractions.Length-1); i>=0; --i )
if( PC.Player.LocalInteractions[i].Class==Default.Class )
{
SRLevelCleanup(PC.Player.LocalInteractions[i]).SwitchToURL = NextURL;
return;
}
C = new(None) Class'SRLevelCleanup';
C.ViewportOwner = PC.Player;
C.Master = PC.Player.InteractionMaster;
i = PC.Player.LocalInteractions.Length;
PC.Player.LocalInteractions.Length = i+1;
PC.Player.LocalInteractions[i] = C;
C.Initialize();
C.SwitchToURL = NextURL;
}
defaultproperties
{
}

View file

@ -0,0 +1,22 @@
class SRLobbyChat extends KFLobbyChat;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super(PopupPageBase).InitComponent( MyController, MyOwner );
TextColor[0] = class'SayMessagePlus'.default.RedTeamColor;
TextColor[1] = class'SayMessagePlus'.default.BlueTeamColor;
TextColor[2] = class'SayMessagePlus'.default.DrawColor;
eb_Send.MyEditBox.OnKeyEvent = InternalOnKeyEvent;
lb_Chat.MyScrollText.bNeverFocus=true;
}
function bool NotifyLevelChange() // Don't keep this one around...
{
bPersistent = false;
return true;
}
defaultproperties
{
}

View file

@ -0,0 +1,66 @@
//-----------------------------------------------------------
//
//-----------------------------------------------------------
class SRLobbyFooter extends LobbyFooter;
function bool OnFooterClick(GUIComponent Sender)
{
local GUIController C;
local PlayerController PC;
PC = PlayerOwner();
C = Controller;
if(Sender == b_Cancel)
{
//Kill Window and exit game/disconnect from server
LobbyMenu(PageOwner).bAllowClose = true;
C.ViewportOwner.Console.ConsoleCommand("DISCONNECT");
PC.ClientCloseMenu(true, false);
C.AutoLoadMenus();
}
else if(Sender == b_Ready)
{
if ( PC.Level.NetMode == NM_Standalone || !PC.PlayerReplicationInfo.bReadyToPlay )
{
//Set Ready
PC.ServerRestartPlayer();
PC.PlayerReplicationInfo.bReadyToPlay = True;
if ( PC.Level.GRI.bMatchHasBegun )
PC.ClientCloseMenu(true, false);
b_Ready.Caption = UnreadyString;
}
else
{
// Spectate map while waiting for players to get ready
LobbyMenu(PageOwner).bAllowClose = true;
PC.ClientCloseMenu(true, false);
}
}
else if (Sender == b_Options)
PC.ClientOpenMenu("KFGUI.KFSettingsPage", false);
else if (Sender == b_Perks)
PC.ClientOpenMenu(string(Class'SRInvasionLoginMenu'), false);
return false;
}
defaultproperties
{
Begin Object Class=GUIButton Name=PerksButton
Caption="Main Menu"
Hint="Go to main menu"
WinTop=0.966146
WinLeft=-0.500000
WinWidth=0.120000
WinHeight=0.033203
RenderWeight=2.000000
TabOrder=2
bBoundToParent=True
ToolTip=None
OnClick=SRLobbyFooter.OnFooterClick
OnKeyEvent=Cancel.InternalOnKeyEvent
End Object
b_Perks=GUIButton'ServerPerks.SRLobbyFooter.PerksButton'
UnreadyString="View map"
}

View file

@ -0,0 +1,465 @@
//-----------------------------------------------------------
//
//-----------------------------------------------------------
class SRLobbyMenu extends LobbyMenu;
struct FPlayerBoxEntry
{
var moCheckBox ReadyBox;
var KFPlayerReadyBar PlayerBox;
var GUIImage PlayerPerk;
var GUILabel PlayerVetLabel;
var bool bIsEmpty;
};
var array<FPlayerBoxEntry> PlayerBoxes;
var automated GUIScrollTextBox tb_ServerMOTD;
var int MaxPlayersOnList;
var bool bMOTDInit,bMOTDHidden;
function AddPlayer( KFPlayerReplicationInfo PRI, int Index, Canvas C )
{
local float Top;
local Material M;
if( Index>=PlayerBoxes.Length )
{
Top = Index*0.045;
PlayerBoxes.Length = Index+1;
PlayerBoxes[Index].ReadyBox = new (None) Class'moCheckBox';
PlayerBoxes[Index].ReadyBox.bValueReadOnly = true;
PlayerBoxes[Index].ReadyBox.ComponentJustification = TXTA_Left;
PlayerBoxes[Index].ReadyBox.CaptionWidth = 0.82;
PlayerBoxes[Index].ReadyBox.LabelColor.B = 0;
PlayerBoxes[Index].ReadyBox.WinTop = 0.0475+Top;
PlayerBoxes[Index].ReadyBox.WinLeft = 0.075;
PlayerBoxes[Index].ReadyBox.WinWidth = 0.4;
PlayerBoxes[Index].ReadyBox.WinHeight = 0.045;
PlayerBoxes[Index].ReadyBox.RenderWeight = 0.55;
PlayerBoxes[Index].ReadyBox.bAcceptsInput = False;
PlayerBoxes[Index].PlayerBox = new (None) Class'KFPlayerReadyBar';
PlayerBoxes[Index].PlayerBox.WinTop = 0.04+Top;
PlayerBoxes[Index].PlayerBox.WinLeft = 0.04;
PlayerBoxes[Index].PlayerBox.WinWidth = 0.35;
PlayerBoxes[Index].PlayerBox.WinHeight = 0.045;
PlayerBoxes[Index].PlayerBox.RenderWeight = 0.35;
PlayerBoxes[Index].PlayerPerk = new (None) Class'GUIImage';
PlayerBoxes[Index].PlayerPerk.ImageStyle = ISTY_Justified;
PlayerBoxes[Index].PlayerPerk.WinTop = 0.043+Top;
PlayerBoxes[Index].PlayerPerk.WinLeft = 0.0418;
PlayerBoxes[Index].PlayerPerk.WinWidth = 0.039;
PlayerBoxes[Index].PlayerPerk.WinHeight = 0.039;
PlayerBoxes[Index].PlayerPerk.RenderWeight = 0.56;
PlayerBoxes[Index].PlayerVetLabel = new (None) Class'GUILabel';
PlayerBoxes[Index].PlayerVetLabel.TextAlign = TXTA_Right;
PlayerBoxes[Index].PlayerVetLabel.TextColor = Class'Canvas'.Static.MakeColor(19,19,19);
PlayerBoxes[Index].PlayerVetLabel.TextFont = "UT2SmallFont";
PlayerBoxes[Index].PlayerVetLabel.WinTop = 0.04+Top;
PlayerBoxes[Index].PlayerVetLabel.WinLeft = 0.22907;
PlayerBoxes[Index].PlayerVetLabel.WinWidth = 0.151172;
PlayerBoxes[Index].PlayerVetLabel.WinHeight = 0.045;
PlayerBoxes[Index].PlayerVetLabel.RenderWeight = 0.5;
AppendComponent(PlayerBoxes[Index].ReadyBox, true);
AppendComponent(PlayerBoxes[Index].PlayerBox, true);
AppendComponent(PlayerBoxes[Index].PlayerPerk, true);
AppendComponent(PlayerBoxes[Index].PlayerVetLabel, true);
Top = (PlayerBoxes[Index].PlayerBox.WinTop+PlayerBoxes[Index].PlayerBox.WinHeight);
if( !bMOTDHidden && Top>=ADBackground.WinTop )
{
ADBackground.WinTop = Top+0.01;
if( (ADBackground.WinTop+ADBackground.WinHeight)>t_ChatBox.WinTop )
{
ADBackground.WinHeight = t_ChatBox.WinTop-ADBackground.WinTop;
if( ADBackground.WinHeight<0.15 )
{
RemoveComponent(ADBackground);
RemoveComponent(tb_ServerMOTD);
bMOTDHidden = true;
}
}
}
}
PlayerBoxes[Index].ReadyBox.Checked(PRI.bReadyToPlay);
PlayerBoxes[Index].ReadyBox.SetCaption(" "$Left(PRI.PlayerName,20));
if ( PRI.ClientVeteranSkill != none )
{
PlayerBoxes[Index].PlayerVetLabel.Caption = "Lv" @ PRI.ClientVeteranSkillLevel @ PRI.ClientVeteranSkill.default.VeterancyName;
if( Class<SRVeterancyTypes>(PRI.ClientVeteranSkill)!=None )
{
Class<SRVeterancyTypes>(PRI.ClientVeteranSkill).Static.PreDrawPerk(C,PRI.ClientVeteranSkillLevel,PlayerBoxes[Index].PlayerPerk.Image,M);
PlayerBoxes[Index].PlayerPerk.ImageColor = C.DrawColor;
}
else
{
PlayerBoxes[Index].PlayerPerk.Image = PRI.ClientVeteranSkill.default.OnHUDIcon;
PlayerBoxes[Index].PlayerPerk.ImageColor = Class'Canvas'.Static.MakeColor(255,255,255);
}
}
else
{
PlayerBoxes[Index].PlayerPerk.Image = None;
PlayerBoxes[Index].PlayerVetLabel.Caption = "";
}
PlayerBoxes[Index].bIsEmpty = false;
}
function EmptyPlayers( int Index )
{
while( Index<PlayerBoxes.Length && !PlayerBoxes[Index].bIsEmpty )
{
PlayerBoxes[Index].ReadyBox.Checked(False);
PlayerBoxes[Index].PlayerPerk.Image = None;
PlayerBoxes[Index].PlayerVetLabel.Caption = "";
PlayerBoxes[Index].ReadyBox.SetCaption("");
PlayerBoxes[Index].bIsEmpty = true;
++Index;
}
}
function InitComponent(GUIController MyC, GUIComponent MyO)
{
Super(UT2k4MainPage).InitComponent(MyC, MyO);
i_Portrait.WinTop = PlayerPortraitBG.ActualTop() + 30;
i_Portrait.WinHeight = PlayerPortraitBG.ActualHeight() - 36;
t_ChatBox.FocusInstead = PerkClickLabel;
}
event Opened(GUIComponent Sender)
{
bShouldUpdateVeterancy = true;
SetTimer(1,true);
}
function DrawPortrait()
{
if( PlayerOwner().PlayerReplicationInfo!=None )
sChar = PlayerOwner().PlayerReplicationInfo.CharacterName;
else sChar = PlayerOwner().GetUrlOption("Character");
if( sCharD!=sChar )
{
sCharD = sChar;
SetPlayerRec();
}
}
function bool NotifyLevelChange()
{
bPersistent = false;
bAllowClose = true;
Controller.CloseMenu(true);
return true;
}
function SetPlayerRec()
{
PlayerRec = Class'xUtil'.Static.FindPlayerRecord(sChar);
i_Portrait.Image = PlayerRec.Portrait;
}
function bool InternalOnPreDraw(Canvas C)
{
local int i, j;
local string StoryString;
local String SkillString;
local KFGameReplicationInfo KFGRI;
local PlayerController PC;
PC = PlayerOwner();
if ( PC == none || PC.Level == none ) // Error?
{
return false;
}
if ( (PC.PlayerReplicationInfo != none && (!PC.PlayerReplicationInfo.bWaitingPlayer || PC.PlayerReplicationInfo.bOnlySpectator)) || PC.Outer.Name=='Entry' )
{
bAllowClose = true;
PC.ClientCloseMenu(True,False);
return false;
}
t_Footer.InternalOnPreDraw(C);
KFGRI = KFGameReplicationInfo(PC.GameReplicationInfo);
if ( KFGRI != none )
WaveLabel.Caption = string(KFGRI.WaveNumber + 1) $ "/" $ string(KFGRI.FinalWave);
else
{
WaveLabel.Caption = "?/?";
return false;
}
C.DrawColor.A = 255;
// First fill in non-ready players.
for ( i = 0; i<KFGRI.PRIArray.Length; i++ )
{
if ( KFGRI.PRIArray[i] == none || KFGRI.PRIArray[i].bOnlySpectator || KFGRI.PRIArray[i].bReadyToPlay || KFPlayerReplicationInfo(KFGRI.PRIArray[i])==None )
continue;
AddPlayer(KFPlayerReplicationInfo(KFGRI.PRIArray[i]),j,C);
if( ++j>=MaxPlayersOnList )
GoTo'DoneIt';
}
// Then comes rest.
for ( i = 0; i < KFGRI.PRIArray.Length; i++ )
{
if ( KFGRI.PRIArray[i]==none || KFGRI.PRIArray[i].bOnlySpectator || !KFGRI.PRIArray[i].bReadyToPlay || KFPlayerReplicationInfo(KFGRI.PRIArray[i])==None )
continue;
if ( KFGRI.PRIArray[i].bReadyToPlay )
{
if ( !bTimeoutTimeLogged )
{
ActivateTimeoutTime = PC.Level.TimeSeconds;
bTimeoutTimeLogged = true;
}
}
AddPlayer(KFPlayerReplicationInfo(KFGRI.PRIArray[i]),j,C);
if( ++j>=MaxPlayersOnList )
GoTo'DoneIt';
}
if( j<MaxPlayersOnList )
EmptyPlayers(j);
DoneIt:
StoryString = PC.Level.Description;
if ( !bStoryBoxFilled )
{
l_StoryBox.LoadStoryText();
bStoryBoxFilled = true;
}
CheckBotButtonAccess();
if ( KFGRI.BaseDifficulty <= 1 )
SkillString = BeginnerString;
else if ( KFGRI.BaseDifficulty <= 2 )
SkillString = NormalString;
else if ( KFGRI.BaseDifficulty <= 4 )
SkillString = HardString;
else if ( KFGRI.BaseDifficulty <= 5 )
SkillString = SuicidalString;
else SkillString = HellOnEarthString;
CurrentMapLabel.Caption = CurrentMapString @ PC.Level.Title;
DifficultyLabel.Caption = DifficultyString @ SkillString;
return false;
}
function DrawPerk(Canvas Canvas)
{
local float X, Y, Width, Height;
local int LevelIndex;
local float TempX, TempY;
local float TempWidth, TempHeight;
local float IconSize, ProgressBarWidth;
local string PerkName, PerkLevelString;
local KFPlayerReplicationInfo KFPRI;
local GameReplicationInfo GRI;
local Material M,SM;
DrawPortrait();
if( !bMOTDHidden )
{
X = 9.f/Canvas.ClipX;
Y = 32.f/Canvas.ClipY;
tb_ServerMOTD.WinWidth = ADBackground.WinWidth-X*2.f;
tb_ServerMOTD.WinHeight = ADBackground.WinHeight-Y*1.25f;
tb_ServerMOTD.WinLeft = ADBackground.WinLeft+X;
tb_ServerMOTD.WinTop = ADBackground.WinTop+Y;
if( !bMOTDInit )
{
GRI = PlayerOwner().Level.GRI;
if( GRI!=None && GRI.MessageOfTheDay!="" )
{
bMOTDInit = true;
tb_ServerMOTD.SetContent(GRI.MessageOfTheDay);
}
}
}
KFPRI = KFPlayerReplicationInfo(PlayerOwner().PlayerReplicationInfo);
if ( KFPRI==None || KFPRI.ClientVeteranSkill==None )
{
if( CurrentVeterancyLevel!=255 )
{
CurrentVeterancyLevel = 255;
lb_PerkEffects.SetContent("None perk active");
}
return;
}
LevelIndex = KFPRI.ClientVeteranSkillLevel;
PerkName = KFPRI.ClientVeteranSkill.default.VeterancyName;
PerkLevelString = "Lv" @ LevelIndex;
//Get the position size etc in pixels
X = (i_BGPerk.WinLeft + 0.003) * Canvas.ClipX;
Y = (i_BGPerk.WinTop + 0.040) * Canvas.ClipY;
Width = (i_BGPerk.WinWidth - 0.006) * Canvas.ClipX;
Height = (i_BGPerk.WinHeight - 0.043) * Canvas.ClipY;
// Offset for the Background
TempX = X;
TempY = Y;
// Initialize the Canvas
Canvas.Style = 1;
Canvas.Font = class'ROHUD'.Static.GetSmallMenuFont(Canvas);
Canvas.SetDrawColor(255, 255, 255, 255);
// Draw Item Background
Canvas.SetPos(TempX, TempY);
//Canvas.DrawTileStretched(ItemBackground, Width, Height);
// Offset and Calculate Icon's Size
TempX += ItemBorder * Height;
TempY += ItemBorder * Height;
IconSize = Height - (ItemBorder * 2.0 * Height);
// Draw Icon
Canvas.SetPos(TempX, TempY);
if( Class<SRVeterancyTypes>(KFPRI.ClientVeteranSkill)!=None )
Class<SRVeterancyTypes>(KFPRI.ClientVeteranSkill).Static.PreDrawPerk(Canvas,KFPRI.ClientVeteranSkillLevel,M,SM);
else M = KFPRI.ClientVeteranSkill.default.OnHUDIcon;
Canvas.DrawTile(M, IconSize, IconSize, 0, 0, M.MaterialUSize(), M.MaterialVSize());
TempX += IconSize + (IconToInfoSpacing * Width);
TempY += TextTopOffset * Height;
ProgressBarWidth = Width - (TempX - X) - (IconToInfoSpacing * Width);
// Select Text Color
Canvas.SetDrawColor(255, 255, 255, 255);
// Draw the Perk's Level name
Canvas.StrLen(PerkName, TempWidth, TempHeight);
Canvas.SetPos(TempX, TempY);
Canvas.DrawText(PerkName);
// Draw the Perk's Level
if ( PerkLevelString != "" )
{
Canvas.StrLen(PerkLevelString, TempWidth, TempHeight);
Canvas.SetPos(TempX + ProgressBarWidth - TempWidth, TempY);
Canvas.DrawText(PerkLevelString);
}
TempY += TempHeight + (0.01 * Height);
if( CurrentVeterancy!=KFPRI.ClientVeteranSkill || CurrentVeterancyLevel!=LevelIndex )
{
CurrentVeterancy = KFPRI.ClientVeteranSkill;
CurrentVeterancyLevel = LevelIndex;
lb_PerkEffects.SetContent(Class<SRVeterancyTypes>(KFPRI.ClientVeteranSkill).Static.GetVetInfoText(LevelIndex,1));
}
}
function bool ShowPerkMenu(GUIComponent Sender)
{
if ( PlayerOwner() != none)
PlayerOwner().ClientOpenMenu(string(Class'SRProfilePage'), false);
return true;
}
defaultproperties
{
Begin Object Class=GUIScrollTextBox Name=MOTDScroll
CharDelay=0.002500
EOLDelay=0.100000
OnCreateComponent=MOTDScroll.InternalOnCreateComponent
WinTop=0.354102
WinLeft=0.072187
WinWidth=0.312375
WinHeight=0.335000
TabOrder=9
End Object
tb_ServerMOTD=GUIScrollTextBox'ServerPerks.SRLobbyMenu.MOTDScroll'
MaxPlayersOnList=18
ReadyBox(0)=None
ReadyBox(1)=None
ReadyBox(2)=None
ReadyBox(3)=None
ReadyBox(4)=None
ReadyBox(5)=None
PlayerBox(0)=None
PlayerBox(1)=None
PlayerBox(2)=None
PlayerBox(3)=None
PlayerBox(4)=None
PlayerBox(5)=None
PlayerPerk(0)=None
PlayerPerk(1)=None
PlayerPerk(2)=None
PlayerPerk(3)=None
PlayerPerk(4)=None
PlayerPerk(5)=None
PlayerVetLabel(0)=None
PlayerVetLabel(1)=None
PlayerVetLabel(2)=None
PlayerVetLabel(3)=None
PlayerVetLabel(4)=None
PlayerVetLabel(5)=None
Begin Object Class=SRLobbyChat Name=ChatBox
OnCreateComponent=ChatBox.InternalOnCreateComponent
WinTop=0.807600
WinLeft=0.016090
WinWidth=0.971410
WinHeight=0.100000
RenderWeight=0.010000
TabOrder=1
OnPreDraw=ChatBox.FloatingPreDraw
OnRendered=ChatBox.FloatingRendered
OnHover=ChatBox.FloatingHover
OnMousePressed=ChatBox.FloatingMousePressed
OnMouseRelease=ChatBox.FloatingMouseRelease
End Object
t_ChatBox=SRLobbyChat'ServerPerks.SRLobbyMenu.ChatBox'
Begin Object Class=SRLobbyFooter Name=BuyFooter
RenderWeight=0.300000
TabOrder=8
bBoundToParent=False
bScaleToParent=False
OnPreDraw=BuyFooter.InternalOnPreDraw
End Object
t_Footer=SRLobbyFooter'ServerPerks.SRLobbyMenu.BuyFooter'
}

View file

@ -0,0 +1,88 @@
// Can be used to add custom GUI components to Esc menu.
class SRMenuAddition extends ReplicationInfo
abstract;
var PlayerController PlayerOwner;
var SRInvasionLoginMenu ActiveMenu;
var bool bHasInit;
replication
{
// Functions server can call.
reliable if( Role==ROLE_Authority )
RepInit;
}
function PostBeginPlay()
{
PlayerOwner = PlayerController(Owner);
GoToState('ServerIdle');
}
simulated function PostNetBeginPlay()
{
bHasInit = true;
}
simulated function RepInit()
{
// Do nothing, simply to force server initiate actor channel immeaditly.
}
simulated function NotifyMenuOpen( SRInvasionLoginMenu M, GUIController C )
{
ActiveMenu = M;
}
simulated function NotifyMenuShown();
simulated function NotifyMenuClosed();
simulated function RemoveComponents(); // Unhook the custom menu buttons here so game doesn't crash.
simulated function Destroyed()
{
local int i;
if( ActiveMenu!=None )
{
for( i=0; i<ActiveMenu.AddOnList.Length; ++i )
if( ActiveMenu.AddOnList[i]==Self )
{
ActiveMenu.AddOnList.Remove(i,1);
break;
}
RemoveComponents();
ActiveMenu = None;
}
}
state ServerIdle
{
function PostNetBeginPlay();
Begin:
Sleep(0.1);
if( PlayerOwner==None || PlayerOwner.Player==None )
Destroy();
if( Viewport(PlayerOwner.Player)!=None )
{
Global.PostNetBeginPlay();
GoToState('LocalHost');
}
else RepInit();
Sleep(2.f);
NetUpdateFrequency = 0.2;
while( PlayerOwner!=None )
Sleep(0.8);
Destroy();
}
state LocalHost
{
Begin:
RemoteRole = ROLE_None;
while( PlayerOwner!=None )
Sleep(0.8);
Destroy();
}
defaultproperties
{
bOnlyRelevantToOwner=True
bAlwaysRelevant=False
NetUpdateFrequency=100.000000
}

View file

@ -0,0 +1,185 @@
class SRModelSelect extends KFModelSelect;
var int CustomOffset;
var localized string AllText,CustomText,StockText;
var array<int> CharCategories;
var array<string> CategoryNames;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local ClientPerkRepLink S;
local int i,j;
local string C,G;
local xUtil.PlayerRecord PR;
super(LockedFloatingWindow).Initcomponent(MyController, MyOwner);
co_Race.MyComboBox.List.bInitializeList = True;
co_Race.ReadOnly(True);
co_Race.AddItem(AllText);
sb_Main.SetPosition(0.040000,0.075000,0.680742,0.555859);
sb_Main.RightPadding = 0.5;
sb_Main.ManageComponent(CharList);
S = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if( S==None || !S.bNoStandardChars )
{
class'xUtil'.static.GetPlayerList(PlayerList);
co_Race.AddItem(StockText);
CategoryNames.Length = 1;
CategoryNames[0] = StockText;
}
CustomOffset = 0;
CharCategories.Length = PlayerList.Length;
// Add in custom mod chars.
if( S!=None )
{
for( i=0; i<S.CustomChars.Length; ++i )
{
C = S.CustomChars[i];
j = InStr(C,":");
if( j==-1 )
G = CustomText;
else
{
G = Left(C,j);
C = Mid(C,j+1);
}
PR = Class'xUtil'.Static.FindPlayerRecord(C);
if( PR.DefaultName~=C )
{
++CustomOffset;
PlayerList.Insert(0,1);
PlayerList[0] = PR;
for( j=0; j<CategoryNames.Length; ++j )
{
if( CategoryNames[j]~=G )
break;
}
if( j==CategoryNames.Length )
{
CategoryNames.Length = j+1;
CategoryNames[j] = G;
co_Race.AddItem(G);
}
CharCategories.Insert(0,1);
CharCategories[0] = j;
}
}
}
co_Race.OnChange=RaceChange;
for( i=(PlayerList.Length-1); i>=CustomOffset; --i )
if( !IsUnLocked(PlayerList[i]) )
PlayerList.Remove(i,1);
RefreshCharacterList("");
// Spawn spinning character actor
if ( SpinnyDude == None )
SpinnyDude = PlayerOwner().spawn(class'XInterface.SpinnyWeap');
SpinnyDude.SetDrawType(DT_Mesh);
SpinnyDude.SetDrawScale(0.9);
SpinnyDude.SpinRate = 0;
}
function RefreshCharacterList(string ExcludedChars, optional string Race)
{
local int i,iCategory;
// Prevent list from calling OnChange events
CharList.List.bNotify = False;
CharList.Clear();
if( Race=="" )
iCategory = -1;
else
{
for( i=0; i<CategoryNames.Length; ++i )
if( CategoryNames[i]~=Race )
{
iCategory = i;
break;
}
}
for(i=0; i<PlayerList.Length; i++)
{
if ( iCategory==-1 || (iCategory==CharCategories[i]) )
CharList.List.Add( Playerlist[i].Portrait, i, 0 );
}
CharList.List.bNotify = True;
}
function RaceChange(GUIComponent Sender)
{
local string specName;
specName = co_Race.GetText();
if( specName~=AllText )
specName="";
RefreshCharacterList("", specName);
}
function ListChange(GUIComponent Sender)
{
local ImageListElem Elem;
CharList.List.GetAtIndex(CharList.List.Index, Elem.Image, Elem.Item,Elem.Locked);
if ( Elem.Item >= 0 && Elem.Item < Playerlist.Length )
{
if ( Elem.Locked==1 )
b_Ok.DisableMe();
else
b_Ok.EnableMe();
sb_Main.Caption = PlayerList[Elem.Item].DefaultName;
}
else sb_Main.Caption = "";
UpdateSpinnyDude();
}
function bool IsUnlocked(xUtil.PlayerRecord Test)
{
local int i;
// If character has no menu filter, just return true
if ( PlayerOwner() == none )
return true;
for( i=0; i<CustomOffset; ++i )
if( PlayerList[i].DefaultName~=Test.DefaultName )
return true;
return PlayerOwner().CharacterAvailable(Test.DefaultName);
}
defaultproperties
{
AllText="All"
CustomText="Custom"
StockText="Stock"
Begin Object Class=moComboBox Name=CharRace
bReadOnly=True
ComponentJustification=TXTA_Left
CaptionWidth=0.250000
Caption="Show"
OnCreateComponent=CharRace.InternalOnCreateComponent
Hint="Filter the available characters."
WinTop=0.880000
WinLeft=0.052733
WinWidth=0.388155
WinHeight=0.042857
TabOrder=4
bBoundToParent=True
bScaleToParent=True
End Object
co_Race=moComboBox'ServerPerks.SRModelSelect.CharRace'
}

View file

@ -0,0 +1,34 @@
class SRPerkProgressList extends KFPerkProgressList;
function PerkChanged(KFSteamStatsAndAchievements KFStatsAndAchievements, int NewPerkIndex)
{
local byte i,lvl;
local int Numerator, Denominator;
local float Progress;
local ClientPerkRepLink ST;
// Update the ItemCount and select the first item
ST = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
lvl = ST.CachePerks[NewPerkIndex].CurrentLevel;
ItemCount = ST.CachePerks[NewPerkIndex].PerkClass.Static.GetRequirementCount(ST,lvl);
SetIndex(0);
RequirementString.Remove(0, RequirementString.Length);
RequirementProgressString.Remove(0, RequirementProgressString.Length);
RequirementProgress.Remove(0, RequirementProgress.Length);
for ( i = 0; i < ItemCount; i++ )
{
Progress = ST.CachePerks[NewPerkIndex].PerkClass.Static.GetPerkProgress(ST,lvl,i,Numerator,Denominator);
RequirementString[RequirementString.Length] = Repl(ST.CachePerks[NewPerkIndex].PerkClass.Static.GetVetInfoText(lvl,2,i), "%x", AddCommas(Denominator));
RequirementProgressString[RequirementProgressString.Length] = FormatNumber(Numerator)$"/"$FormatNumber(Denominator);
RequirementProgress[RequirementProgress.Length] = Progress;
}
if ( MyScrollBar != none )
MyScrollBar.AlignThumb();
}
defaultproperties
{
}

View file

@ -0,0 +1,11 @@
class SRPerkProgressListBox extends KFPerkProgressListBox;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
DefaultListClass = string(Class'SRPerkProgressList');
Super.InitComponent(MyController,MyOwner);
}
defaultproperties
{
}

View file

@ -0,0 +1,145 @@
class SRPerkSelectList extends KFPerkSelectList;
function InitList(KFSteamStatsAndAchievements StatsAndAchievements)
{
local int i;
local KFPlayerController KFPC;
local ClientPerkRepLink ST;
local class<KFVeterancyTypes> CurCL;
// Grab the Player Controller for later use
KFPC = KFPlayerController(PlayerOwner());
if( KFPC!=None && KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo)!=None )
CurCL = KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo).ClientVeteranSkill;
// Hold onto our reference
ST = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if( ST==None )
return;
// Update the ItemCount and select the first item
ItemCount = ST.CachePerks.Length;
SetIndex(0);
PerkName.Remove(0, PerkName.Length);
PerkLevelString.Remove(0, PerkLevelString.Length);
PerkProgress.Remove(0, PerkProgress.Length);
for ( i = 0; i < ItemCount; i++ )
{
PerkName[PerkName.Length] = ST.CachePerks[i].PerkClass.Static.GetVetInfoText(ST.CachePerks[i].CurrentLevel,3);
if( ST.CachePerks[i].CurrentLevel==0 )
PerkLevelString[PerkLevelString.Length] = "N/A";
else PerkLevelString[PerkLevelString.Length] = LvAbbrString @ (ST.CachePerks[i].CurrentLevel-1);
PerkProgress[PerkProgress.Length] = ST.CachePerks[i].PerkClass.Static.GetTotalProgress(ST,ST.CachePerks[i].CurrentLevel);
if ( ST.CachePerks[i].PerkClass==CurCL )
SetIndex(i);
}
if ( bNotify )
CheckLinkedObjects(Self);
if ( MyScrollBar != none )
MyScrollBar.AlignThumb();
}
function bool PreDraw(Canvas Canvas)
{
if ( Controller.MouseX >= ClientBounds[0] && Controller.MouseX <= ClientBounds[2] && Controller.MouseY >= ClientBounds[1] )
{
// Figure out which Item we're clicking on
MouseOverIndex = Top + ((Controller.MouseY - ClientBounds[1]) / ItemHeight);
if ( MouseOverIndex >= ItemCount )
{
MouseOverIndex = -1;
}
}
else
{
MouseOverIndex = -1;
}
return false;
}
function DrawPerk(Canvas Canvas, int CurIndex, float X, float Y, float Width, float Height, bool bSelected, bool bPending)
{
local float TempX, TempY;
local float IconSize, ProgressBarWidth;
local float TempWidth, TempHeight;
local ClientPerkRepLink ST;
local Material M,SM;
ST = Class'ClientPerkRepLink'.Static.FindStats(Canvas.Viewport.Actor);
if( ST==None )
return;
// Offset for the Background
TempX = X;
TempY = Y + ItemSpacing / 2.0;
// Initialize the Canvas
Canvas.Style = 1;
Canvas.Font = class'ROHUD'.Static.GetSmallMenuFont(Canvas);
Canvas.SetDrawColor(255, 255, 255, 255);
// Draw Item Background
Canvas.SetPos(TempX, TempY);
if ( bSelected )
{
Canvas.DrawTileStretched(SelectedPerkBackground, IconSize, IconSize);
Canvas.SetPos(TempX + IconSize - 1.0, Y + 7.0);
Canvas.DrawTileStretched(SelectedInfoBackground, Width - IconSize, Height - ItemSpacing - 14);
}
else
{
Canvas.DrawTileStretched(PerkBackground, IconSize, IconSize);
Canvas.SetPos(TempX + IconSize - 1.0, Y + 7.0);
Canvas.DrawTileStretched(InfoBackground, Width - IconSize, Height - ItemSpacing - 14);
}
// Offset and Calculate Icon's Size
TempX += ItemBorder * Height;
TempY += ItemBorder * Height;
IconSize = Height - ItemSpacing - (ItemBorder * 2.0 * Height);
// Draw Icon
Canvas.SetPos(TempX, TempY);
ST.CachePerks[CurIndex].PerkClass.Static.PreDrawPerk(Canvas,Max(ST.CachePerks[CurIndex].CurrentLevel,1)-1,M,SM);
Canvas.DrawTile(M, IconSize, IconSize, 0, 0, M.MaterialUSize(), M.MaterialVSize());
TempX += IconSize + (IconToInfoSpacing * Width);
TempY += TextTopOffset * Height;
ProgressBarWidth = Width - (TempX - X) - (IconToInfoSpacing * Width);
// Select Text Color
if ( CurIndex == MouseOverIndex )
Canvas.SetDrawColor(255, 0, 0, 255);
else Canvas.SetDrawColor(255, 255, 255, 255);
// Draw the Perk's Level Name
Canvas.StrLen(PerkName[CurIndex], TempWidth, TempHeight);
Canvas.SetPos(TempX, TempY);
Canvas.DrawText(PerkName[CurIndex]);
// Draw the Perk's Level
if ( PerkLevelString[CurIndex] != "" )
{
Canvas.StrLen(PerkLevelString[CurIndex], TempWidth, TempHeight);
Canvas.SetPos(TempX + ProgressBarWidth - TempWidth, TempY);
Canvas.DrawText(PerkLevelString[CurIndex]);
}
TempY += TempHeight + (0.01 * Height);
// Draw Progress Bar
Canvas.SetDrawColor(255, 255, 255, 255);
Canvas.SetPos(TempX, TempY);
Canvas.DrawTileStretched(ProgressBarBackground, ProgressBarWidth, ProgressBarHeight * Height);
Canvas.SetPos(TempX, TempY);
Canvas.DrawTileStretched(ProgressBarForeground, ProgressBarWidth * PerkProgress[CurIndex], ProgressBarHeight * Height);
}
defaultproperties
{
}

View file

@ -0,0 +1,11 @@
class SRPerkSelectListBox extends KFPerkSelectListBox;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
DefaultListClass = string(Class'SRPerkSelectList');
Super.InitComponent(MyController,MyOwner);
}
defaultproperties
{
}

View file

@ -0,0 +1,13 @@
class SRProfilePage extends KFProfilePage;
defaultproperties
{
Begin Object Class=SRTab_Profile Name=Panel
WinTop=0.010000
WinLeft=0.010000
WinWidth=0.980000
WinHeight=0.960000
End Object
ProfilePanel=SRTab_Profile'ServerPerks.SRProfilePage.Panel'
}

View file

@ -0,0 +1,505 @@
class SRScoreBoard extends KFScoreBoard;
#exec TEXTURE IMPORT FILE="Textures\Shield.pcx" NAME="I_AdminShield" GROUP="Icons" MIPS=0 MASKED=1
var bool bDrawLevelDigits;
var byte FrameCounter;
var localized string NotShownInfo,PlayerCountText,SpectatorCountText,AliveCountText,BotText;
simulated static final function Material GetCountryFlag( PlayerReplicationInfo PRI )
{
if( PRI.Skins.Length!=1 )
{
PRI.Skins.Length = 1;
if( Mid(PRI.PlayerName,4,1)=="]" )
PRI.Skins[0] = Material(DynamicLoadObject("CountryFlagsTex."$Mid(PRI.PlayerName,1,3),Class'Material',true));
else PRI.Skins[0] = Material(DynamicLoadObject("CountryFlagsTex."$Mid(PRI.PlayerName,1,2),Class'Material',true));
}
return PRI.Skins[0];
}
simulated static final function float DrawCountryName( Canvas C, PlayerReplicationInfo PRI, float X, float Y, optional byte MaxLen )
{
local float XL,YL,Result;
local Color Cl;
local Material M;
local string S;
if( MaxLen>0 )
S = Left(PRI.PlayerName,MaxLen);
else S = PRI.PlayerName;
if( Mid(S,0,1)=="[" )
{
if( Mid(S,4,1)=="]" )
{
M = GetCountryFlag(PRI);
if( M!=None )
{
C.TextSize("ABC",XL,YL);
Cl = C.DrawColor;
C.DrawColor = Class'HudBase'.Default.WhiteColor;
C.SetPos(X, Y+(YL*0.2));
C.DrawTile(M, YL, YL, 0, 0, M.MaterialUSize(), M.MaterialVSize());
X+=YL;
S = Mid(S,5);
C.DrawColor = Cl;
}
}
else if( Mid(S,3,1)=="]" )
{
M = GetCountryFlag(PRI);
if( M!=None )
{
C.TextSize("ABC",XL,YL);
Cl = C.DrawColor;
C.DrawColor = Class'HudBase'.Default.WhiteColor;
C.SetPos(X, Y+(YL*0.2));
C.DrawTile(M, YL, YL, 0, 0, M.MaterialUSize(), M.MaterialVSize());
X+=YL;
S = Mid(S,4);
C.DrawColor = Cl;
}
}
}
C.SetPos(X, Y);
C.DrawTextClipped(S,false);
C.TextSize(S,Result,XL);
return Result + YL;
}
simulated static final function TextSizeCountry( Canvas C, PlayerReplicationInfo PRI, out float XL, out float YL )
{
local float XS;
local Material M;
local string S;
XL = 0;
S = PRI.PlayerName;
if( Mid(S,0,1)=="[" )
{
if( Mid(S,4,1)=="]" )
{
M = GetCountryFlag(PRI);
if( M!=None )
{
C.TextSize("ABC",XS,YL);
XL = YL;
S = Mid(S,5);
}
}
else if( Mid(S,3,1)=="]" )
{
M = GetCountryFlag(PRI);
if( M!=None )
{
C.TextSize("ABC",XS,YL);
XL = YL;
S = Mid(S,4);
}
}
}
C.TextSize(S,XS,YL);
XL+=XS;
}
simulated static final function DrawProgressBar( Canvas C, float X, float Y, float XS, float YS, float Value )
{
C.DrawColor.A = 64;
C.SetPos(X, Y);
C.DrawTileStretched(Texture'thinpipe_b',XS,YS);
if( Value>0.f )
{
C.DrawColor.A = 150;
C.SetPos(X,Y);
C.DrawTileStretched(Texture'thinpipe_f',XS*Value,YS);
}
}
simulated event UpdateScoreBoard(Canvas Canvas)
{
local PlayerReplicationInfo PRI, OwnerPRI;
local KFPlayerReplicationInfo KFPRI;
local KF_StoryPRI StoryPRI;
local int i, FontReduction, NetXPos, PlayerCount, HeaderOffsetY, HeadFoot, MessageFoot, PlayerBoxSizeY, BoxSpaceY, NameXPos, BoxTextOffsetY, OwnerOffset, HealthXPos, BoxXPos,KillsXPos, TitleYPos, BoxWidth, VetXPos, NotShownCount;
local float XL,YL;
local float deathsXL, KillsXL, NetXL, HealthXL, MaxNamePos, KillWidthX, CashXPos, TimeXPos, PProgressXS, StoryIconXPos;
local Material VeterancyBox,StarBox;
local string S;
local byte Stars;
local KF_StoryObjective CurrentObj;
local Font LvlFont,OrgFont;
if( ++FrameCounter>250 )
{
FrameCounter = 0;
bDrawLevelDigits = !bDrawLevelDigits;
}
OwnerPRI = KFPlayerController(Owner).PlayerReplicationInfo;
OwnerOffset = -1;
for ( i = 0; i < GRI.PRIArray.Length; i++)
{
PRI = GRI.PRIArray[i];
if ( !PRI.bOnlySpectator )
{
if( !PRI.bOutOfLives && KFPlayerReplicationInfo(PRI).PlayerHealth>0 )
++HeadFoot;
if ( PRI == OwnerPRI )
OwnerOffset = i;
PlayerCount++;
}
else ++NetXPos;
}
// First, draw title.
if(KF_StoryGRI(GRI) != none)
{
CurrentObj = KF_StoryGRI(GRI).GetCurrentObjective();
if(CurrentObj != none)
S = CurrentObj.HUD_Header.Header_Text;
}
else S = WaveString @ (InvasionGameReplicationInfo(GRI).WaveNumber + 1);
S = SkillLevel[Clamp(InvasionGameReplicationInfo(GRI).BaseDifficulty, 0, 7)] $ " | " $ S $ " | " $ Level.Title $ " | " $ FormatTime(GRI.ElapsedTime);
Canvas.Font = class'ROHud'.static.GetSmallMenuFont(Canvas);
Canvas.TextSize(S, XL,YL);
Canvas.DrawColor = HUDClass.default.RedColor;
Canvas.Style = ERenderStyle.STY_Normal;
HeaderOffsetY = Canvas.ClipY * 0.11;
Canvas.SetPos(0.5 * (Canvas.ClipX - XL), HeaderOffsetY);
Canvas.DrawTextClipped(S);
// Second title line
S = PlayerCountText@PlayerCount@SpectatorCountText@NetXPos@AliveCountText@HeadFoot;
Canvas.TextSize(S, XL,YL);
HeaderOffsetY+=YL;
Canvas.SetPos(0.5 * (Canvas.ClipX - XL), HeaderOffsetY);
Canvas.DrawTextClipped(S);
HeaderOffsetY+=(YL*3.f);
// Select best font size and box size to fit as many players as possible on screen
if ( Canvas.ClipX < 600 )
i = 4;
else if ( Canvas.ClipX < 800 )
i = 3;
else if ( Canvas.ClipX < 1000 )
i = 2;
else if ( Canvas.ClipX < 1200 )
i = 1;
else i = 0;
Canvas.Font = class'ROHud'.static.LoadMenuFontStatic(i);
Canvas.TextSize("Test", XL, YL);
PlayerBoxSizeY = 1.2 * YL;
BoxSpaceY = 0.25 * YL;
while( ((PlayerBoxSizeY+BoxSpaceY)*PlayerCount)>(Canvas.ClipY-HeaderOffsetY) )
{
if( ++i>=5 || ++FontReduction>=3 ) // Shrink font, if too small then break loop.
{
// We need to remove some player names here to make it fit.
NotShownCount = PlayerCount-int((Canvas.ClipY-HeaderOffsetY)/(PlayerBoxSizeY+BoxSpaceY))+1;
PlayerCount-=NotShownCount;
break;
}
Canvas.Font = class'ROHud'.static.LoadMenuFontStatic(i);
Canvas.TextSize("Test", XL, YL);
PlayerBoxSizeY = 1.2 * YL;
BoxSpaceY = 0.25 * YL;
}
if( bDrawLevelDigits )
{
LvlFont = class'ROHud'.static.LoadMenuFontStatic(i+2);
OrgFont = Canvas.Font;
}
HeadFoot = 7 * YL;
MessageFoot = 1.5 * HeadFoot;
BoxWidth = 0.9 * Canvas.ClipX;
BoxXPos = 0.5 * (Canvas.ClipX - BoxWidth);
BoxWidth = Canvas.ClipX - 2 * BoxXPos;
VetXPos = BoxXPos + 0.0001 * BoxWidth;
NameXPos = VetXPos + PlayerBoxSizeY*1.75f;
StoryIconXPos = BoxXPos + 0.48 * BoxWidth;
KillsXPos = BoxXPos + 0.55 * BoxWidth;
CashXPos = BoxXPos + 0.65 * BoxWidth;
HealthXpos = BoxXPos + 0.75 * BoxWidth;
TimeXPos = BoxXPos + 0.87 * BoxWidth;
NetXPos = BoxXPos + 0.996 * BoxWidth;
PProgressXS = BoxWidth * 0.1f;
// draw background boxes
Canvas.Style = ERenderStyle.STY_Alpha;
Canvas.DrawColor = HUDClass.default.WhiteColor;
Canvas.DrawColor.A = 128;
for ( i = 0; i < PlayerCount; i++ )
{
Canvas.SetPos(BoxXPos, HeaderOffsetY + (PlayerBoxSizeY + BoxSpaceY) * i);
Canvas.DrawTileStretched( BoxMaterial, BoxWidth, PlayerBoxSizeY);
}
if( NotShownCount>0 ) // Add box for not shown players.
{
Canvas.DrawColor = HUDClass.default.RedColor;
Canvas.SetPos(BoxXPos, HeaderOffsetY + (PlayerBoxSizeY + BoxSpaceY) * PlayerCount);
Canvas.DrawTileStretched( BoxMaterial, BoxWidth, PlayerBoxSizeY);
Canvas.DrawColor = HUDClass.default.WhiteColor;
}
// Draw headers
TitleYPos = HeaderOffsetY - 1.1 * YL;
Canvas.TextSize(HealthText, HealthXL, YL);
Canvas.TextSize(DeathsText, DeathsXL, YL);
Canvas.TextSize(KillsText, KillsXL, YL);
Canvas.TextSize(NetText, NetXL, YL);
Canvas.DrawColor = HUDClass.default.WhiteColor;
Canvas.SetPos(NameXPos, TitleYPos);
Canvas.DrawTextClipped(PlayerText);
Canvas.SetPos(KillsXPos - 0.5 * KillsXL, TitleYPos);
Canvas.DrawTextClipped(KillsText);
Canvas.TextSize(PointsText, XL, YL);
Canvas.SetPos(CashXPos - 0.5 * XL, TitleYPos);
Canvas.DrawTextClipped(PointsText);
Canvas.TextSize(TimeText, XL, YL);
Canvas.SetPos(TimeXPos - 0.5 * XL, TitleYPos);
Canvas.DrawTextClipped(TimeText);
Canvas.SetPos(HealthXPos - 0.5 * HealthXL, TitleYPos);
Canvas.DrawTextClipped(HealthText);
Canvas.Style = ERenderStyle.STY_Normal;
Canvas.DrawColor = HUDClass.default.WhiteColor;
Canvas.SetPos(0.5 * Canvas.ClipX, HeaderOffsetY + 4);
Canvas.DrawColor = HUDClass.default.WhiteColor;
Canvas.SetPos(NetXPos - NetXL, TitleYPos);
Canvas.DrawTextClipped(NetText);
BoxTextOffsetY = HeaderOffsetY + 0.5 * (PlayerBoxSizeY - YL);
Canvas.DrawColor = HUDClass.default.WhiteColor;
MaxNamePos = Canvas.ClipX;
Canvas.ClipX = KillsXPos - 4.f;
for ( i = 0; i < PlayerCount; i++ )
{
if( i == OwnerOffset )
{
Canvas.DrawColor.G = 0;
Canvas.DrawColor.B = 0;
}
else
{
Canvas.DrawColor.G = 255;
Canvas.DrawColor.B = 255;
}
DrawCountryName(Canvas,GRI.PRIArray[i],NameXPos,(PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY);
}
if( NotShownCount>0 ) // Draw not shown info
{
Canvas.DrawColor.G = 255;
Canvas.DrawColor.B = 0;
Canvas.SetPos(NameXPos, (PlayerBoxSizeY + BoxSpaceY)*PlayerCount + BoxTextOffsetY);
Canvas.DrawText(NotShownCount@NotShownInfo,true);
}
Canvas.ClipX = MaxNamePos;
Canvas.DrawColor = HUDClass.default.WhiteColor;
Canvas.Style = ERenderStyle.STY_Normal;
// Draw the player informations.
for ( i = 0; i < PlayerCount; i++ )
{
PRI = GRI.PRIArray[i];
KFPRI = KFPlayerReplicationInfo(PRI);
StoryPRI = KF_StoryPRI(PRI);
Canvas.DrawColor = HUDClass.default.WhiteColor;
// Display admin.
if( PRI.bAdmin && !bDrawLevelDigits )
{
Canvas.SetPos(BoxXPos - PlayerBoxSizeY, (PlayerBoxSizeY + BoxSpaceY) * i + HeaderOffsetY + PlayerBoxSizeY*0.25);
XL = PlayerBoxSizeY*0.5;
Canvas.DrawTile(Texture'I_AdminShield', XL, XL, 0, 0, Texture'I_AdminShield'.USize, Texture'I_AdminShield'.VSize);
}
// display Story Icon
if ( StoryPRI != none )
{
StarBox = StoryPRI.GetFloatingIconMat();
if ( StarBox != none )
{
Canvas.SetPos(StoryIconXPos, (PlayerBoxSizeY + BoxSpaceY) * i + HeaderOffsetY + 1 );
Canvas.DrawTile(StarBox, PlayerBoxSizeY*0.8, PlayerBoxSizeY*0.8, 0, 0, StarBox.MaterialUSize(), StarBox.MaterialVSize());
}
}
// Display perks.
if ( KFPRI!=None && Class<SRVeterancyTypes>(KFPRI.ClientVeteranSkill)!=none )
{
Stars = Class<SRVeterancyTypes>(KFPRI.ClientVeteranSkill).Static.PreDrawPerk(Canvas
,KFPRI.ClientVeteranSkillLevel,VeterancyBox,StarBox);
if ( VeterancyBox != None )
{
YL = HeaderOffsetY+(PlayerBoxSizeY+BoxSpaceY)*i;
DrawPerkWithStars(Canvas,VetXPos,YL,PlayerBoxSizeY,Stars,VeterancyBox,StarBox);
if( bDrawLevelDigits )
{
Canvas.SetPos(BoxXPos,YL);
Canvas.Font = LvlFont;
Canvas.DrawColor = HUDClass.default.GoldColor;
S = "Lv"$string(KFPRI.ClientVeteranSkillLevel);
Canvas.TextSize(S,XL,YL);
Canvas.CurX-=(XL*1.025);
Canvas.CurY+=(PlayerBoxSizeY-YL)*0.5;
Canvas.DrawTextClipped(S);
Canvas.Font = OrgFont;
}
}
Canvas.DrawColor = HUDClass.default.WhiteColor;
// Draw perk progress
if( !PRI.bBot && KFPRI.ThreeSecondScore>=0 )
{
YL = float(KFPRI.ThreeSecondScore) / 10000.f;
DrawProgressBar(Canvas,KillsXPos-PProgressXS*1.5,HeaderOffsetY + (PlayerBoxSizeY + BoxSpaceY) * i + PlayerBoxSizeY*0.4,PProgressXS,PlayerBoxSizeY*0.2,FClamp(YL,0.f,1.f));
Canvas.DrawColor.A = 255;
}
}
// draw kills
if( KFPRI!=None )
{
Canvas.TextSize(KFPRI.Kills, KillWidthX, YL);
Canvas.SetPos(KillsXPos - 0.5 * KillWidthX, (PlayerBoxSizeY + BoxSpaceY) * i + BoxTextOffsetY);
Canvas.DrawTextClipped(KFPRI.Kills);
}
// draw cash
S = string(int(PRI.Score));
Canvas.TextSize(S, XL, YL);
Canvas.SetPos(CashXPos-XL*0.5f, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY);
Canvas.DrawText(S,true);
// draw time
if( GRI.ElapsedTime<PRI.StartTime ) // Login timer error, fix it.
GRI.ElapsedTime = PRI.StartTime;
S = FormatTime(GRI.ElapsedTime-PRI.StartTime);
Canvas.TextSize(S, XL, YL);
Canvas.SetPos(TimeXPos-XL*0.5f, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY);
Canvas.DrawText(S,true);
// Draw ping
if ( !GRI.bMatchHasBegun )
{
if ( PRI.bReadyToPlay )
S = ReadyText;
else S = NotReadyText;
}
else if( !PRI.bBot )
S = string(PRI.Ping*4);
else S = BotText;
Canvas.TextSize(S, XL, YL);
Canvas.SetPos(NetXPos-XL, (PlayerBoxSizeY + BoxSpaceY) * i + BoxTextOffsetY);
Canvas.DrawTextClipped(S);
// draw healths
if ( PRI.bOutOfLives || KFPRI==None || KFPRI.PlayerHealth<=0 )
{
Canvas.DrawColor = HUDClass.default.RedColor;
S = OutText;
}
else
{
if( KFPRI.PlayerHealth>=90 )
Canvas.DrawColor = HUDClass.default.GreenColor;
else if( KFPRI.PlayerHealth>=50 )
Canvas.DrawColor = HUDClass.default.GoldColor;
else Canvas.DrawColor = HUDClass.default.RedColor;
S = KFPlayerReplicationInfo(PRI).PlayerHealth@HealthyString;
}
Canvas.TextSize(S, XL, YL);
Canvas.SetPos(HealthXpos - 0.5 * XL, (PlayerBoxSizeY + BoxSpaceY) * i + BoxTextOffsetY);
Canvas.DrawTextClipped(S);
}
}
simulated final function DrawPerkWithStars( Canvas C, float X, float Y, float Scale, int Stars, Material PerkIcon, Material StarIcon )
{
local byte i;
C.SetPos(X,Y);
C.DrawTile(PerkIcon, Scale, Scale, 0, 0, PerkIcon.MaterialUSize(), PerkIcon.MaterialVSize());
if( Stars==0 || StarIcon==None )
return;
Y+=Scale*0.9f;
X+=Scale*0.8f;
Scale*=0.2f;
while( Stars>0 )
{
for( i=1; i<=Min(5,Stars); ++i )
{
C.SetPos(X,Y-(i*Scale*0.8f));
C.DrawTile(StarIcon, Scale, Scale, 0, 0, StarIcon.MaterialUSize(), StarIcon.MaterialVSize());
}
X+=Scale;
Stars-=5;
}
}
simulated function bool InOrder( PlayerReplicationInfo P1, PlayerReplicationInfo P2 )
{
local KFPlayerReplicationInfo P11,P22;
if( P1.bOnlySpectator )
return P2.bOnlySpectator;
else if ( P2.bOnlySpectator )
return true;
if( P1.Kills < P2.Kills )
return false;
else if( P1.Kills==P2.Kills )
{
P11 = KFPlayerReplicationInfo(P1);
P22 = KFPlayerReplicationInfo(P2);
if( P11==None || P22==None )
{
// Go for dosh
if( P1.Score < P2.Score )
return false;
else if( P1.Score == P2.Score)
return (P1.PlayerName<P2.PlayerName); // Go for name.
}
else
{
// Kills is equal, go for assists.
if( P11.KillAssists < P22.KillAssists )
return false;
else if( P11.KillAssists==P22.KillAssists )
{
// Go for dosh
if( P1.Score < P2.Score )
return false;
else if( P1.Score == P2.Score)
return (P1.PlayerName<P2.PlayerName); // Go for name.
}
}
}
return true;
}
defaultproperties
{
NotShownInfo="player names not shown"
PlayerCountText="Players:"
SpectatorCountText="| Spectators:"
AliveCountText="| Alive players:"
BotText="BOT"
HealthyString="HP"
}

View file

@ -0,0 +1,169 @@
class SRStatList extends GUIVertList;
// Display
var texture InfoBackground;
// State
var localized array<string> ProgressName;
var array<string> StatProgress;
var array<byte> DisplayFormat; // 0 - value, 1 - time
function bool PreDraw(Canvas Canvas)
{
return false;
}
function InitList( ClientPerkRepLink L )
{
local SRCustomProgress P;
local int i;
for( P=L.CustomLink; P!=None; P=P.NextLink )
++i;
ItemCount = Default.ProgressName.Length+i;
ProgressName.Length = ItemCount;
StatProgress.Length = ItemCount;
i = Default.ProgressName.Length;
for( P=L.CustomLink; P!=None; P=P.NextLink )
{
ProgressName[i] = P.ProgressName;
StatProgress[i] = P.GetDisplayString();
++i;
}
// Update the ItemCount and select the first item
SetIndex(0);
StatProgress[0] = string(L.RDamageHealedStat);
StatProgress[1] = string(L.RWeldingPointsStat);
StatProgress[2] = string(L.RShotgunDamageStat);
StatProgress[3] = string(L.RHeadshotKillsStat);
StatProgress[4] = string(L.RChainsawKills);
StatProgress[5] = string(L.RStalkerKillsStat);
StatProgress[6] = string(L.RBullpupDamageStat);
StatProgress[7] = string(L.RMeleeDamageStat);
StatProgress[8] = string(L.RFlameThrowerDamageStat);
StatProgress[9] = string(L.RSelfHealsStat);
StatProgress[10] = string(L.RSoleSurvivorWavesStat);
StatProgress[11] = string(L.RCashDonatedStat);
StatProgress[12] = string(L.RFeedingKillsStat);
StatProgress[13] = string(L.RHuntingShotgunKills);
StatProgress[14] = string(L.RBurningCrossbowKillsStat);
StatProgress[15] = string(L.RGibbedFleshpoundsStat);
StatProgress[16] = string(L.RStalkersKilledWithExplosivesStat);
StatProgress[17] = string(L.RExplosivesDamageStat);
StatProgress[18] = string(L.RGibbedEnemiesStat);
StatProgress[19] = string(L.RBloatKillsStat);
StatProgress[20] = string(L.RTotalZedTimeStat);
StatProgress[21] = string(L.RSirenKillsStat);
StatProgress[22] = string(L.RKillsStat);
StatProgress[23] = string(L.RMedicKnifeKills);
StatProgress[24] = string(L.TotalPlayTime);
StatProgress[25] = string(L.WinsCount);
StatProgress[26] = string(L.LostsCount);
for( i=0; i<DisplayFormat.Length; ++i )
if( DisplayFormat[i]==1 )
StatProgress[i] = GetTimeText(int(StatProgress[i]));
if ( bNotify )
{
CheckLinkedObjects(Self);
}
if ( MyScrollBar != none )
{
MyScrollBar.AlignThumb();
}
}
final function string GetTimeText( int V )
{
local int Hours, Minutes;
Minutes = V / 60;
Hours = Minutes / 60;
V -= (Minutes * 60);
Minutes -= (Hours * 60);
return Eval(Hours<10,"0"$Hours,string(Hours))$":"$Eval(Minutes<10,"0"$Minutes,string(Minutes))$":"$Eval(V<10,"0"$V,string(V));
}
function DrawStat(Canvas Canvas, int CurIndex, float X, float Y, float Width, float Height, bool bSelected, bool bPending)
{
local float TempX, TempY;
local float TempWidth, TempHeight;
// Offset for the Background
TempX = X;
TempY = Y;
// Initialize the Canvas
Canvas.Style = 1;
Canvas.Font = class'ROHUD'.Static.GetSmallMenuFont(Canvas);
Canvas.SetDrawColor(255, 255, 255, 255);
// Draw Item Background
Canvas.SetPos(TempX, TempY);
Canvas.DrawTileStretched(InfoBackground, Width, Height);
// Select Text Color
Canvas.SetDrawColor(0, 0, 0, 255);
// Draw progress type.
Canvas.TextSize(ProgressName[CurIndex],TempWidth,TempHeight);
TempX += Width*0.1f;
TempY += (Height-TempHeight)*0.5f;
Canvas.SetPos(TempX, TempY);
Canvas.DrawText(ProgressName[CurIndex]$":");
// Draw current progress.
Canvas.TextSize(StatProgress[CurIndex],TempWidth,TempHeight);
Canvas.SetPos(X + Width*0.88f - TempWidth, TempY);
Canvas.DrawText(StatProgress[CurIndex]);
}
function float PerkHeight(Canvas c)
{
return (MenuOwner.ActualHeight() / 14.0) - 1.0;
}
defaultproperties
{
InfoBackground=Texture'KF_InterfaceArt_tex.Menu.Item_box_bar'
ProgressName(0)="Healed damage"
ProgressName(1)="Welded hitpoints"
ProgressName(2)="Shotgun damage"
ProgressName(3)="Headshot kills"
ProgressName(4)="Chainsaw kills"
ProgressName(5)="Stalker kills"
ProgressName(6)="Bullpup/AK47/SCAR damage"
ProgressName(7)="Melee damage"
ProgressName(8)="Flame thrower damage"
ProgressName(9)="Self healed count"
ProgressName(10)="Sole survivor waves count"
ProgressName(11)="Cash donated"
ProgressName(12)="Feeding zombies killed"
ProgressName(13)="Hunting shotgun kills"
ProgressName(14)="Burning crossbow kills"
ProgressName(15)="Gibbed fleshpounds"
ProgressName(16)="Stalkers killed with explosives"
ProgressName(17)="Explosives damage count"
ProgressName(18)="Gibbed zombies count"
ProgressName(19)="Bloat kills"
ProgressName(20)="Total ZED-time"
ProgressName(21)="Siren kills"
ProgressName(22)="Total kills"
ProgressName(23)="Knife kills as medic"
ProgressName(24)="Total playtime"
ProgressName(25)="Won games"
ProgressName(26)="Lost games"
DisplayFormat(20)=1
DisplayFormat(24)=1
GetItemHeight=SRStatList.PerkHeight
ItemCount=27
OnDrawItem=SRStatList.DrawStat
FontScale=FNS_Medium
OnPreDraw=SRStatList.PreDraw
}

View file

@ -0,0 +1,25 @@
class SRStatListBox extends GUIListBoxBase;
var SRStatList List;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
DefaultListClass = string(Class'SRStatList');
Super.InitComponent(MyController,MyOwner);
List = SRStatList(AddComponent(DefaultListClass));
if (List == None)
{
Warn(Class$".InitComponent - Could not create default list ["$DefaultListClass$"]");
return;
}
InitBaseList(List);
}
function int GetIndex()
{
return List.Index;
}
defaultproperties
{
}

View file

@ -0,0 +1,27 @@
// Template class.
Class SRStatsBase extends KFSteamStatsAndAchievements
Abstract;
var ClientPerkRepLink Rep;
var KFPlayerController PlayerOwner;
var bool bStatsReadyNow;
function int GetID();
function SetID( int ID );
function ChangeCharacter( string CN );
function ApplyCharacter( string CN );
function AddHeadshotKills(int Amount);
function AddStalkerKills(int Amount);
function ServerSelectPerkName( name N );
function ServerSelectPerk( Class<SRVeterancyTypes> VetType );
function NotifyStatChanged();
defaultproperties
{
bInitialized=True
bUsedCheats=True
RemoteRole=ROLE_None
bNetNotify=False
}

View file

@ -0,0 +1,49 @@
Class SRSteamStatsGet extends KFSteamStatsAndAchievements
transient;
var ClientPerkRepLink Link;
var bool bNoInit;
simulated event PostBeginPlay()
{
if( bNoInit )
return;
PCOwner = Level.GetLocalPlayerController();
Initialize(PCOwner);
GetStatsAndAchievements();
}
simulated event PostNetBeginPlay();
simulated event OnStatsAndAchievementsReady()
{
local int i,d;
InitStatInt(OwnedWeaponDLC, GetOwnedWeaponDLC());
for( i=(Link.ShopInventory.Length-1); i>=0; --i )
if( Link.ShopInventory[i].bDLCLocked!=0 )
{
d = class<KFWeapon>(Link.ShopInventory[i].PC.Default.InventoryType).Default.AppID;
if( d!=0 )
{
if( PlayerOwnsWeaponDLC(d) )
Link.ShopInventory[i].bDLCLocked = 0;
else if( class<KFWeapon>(Link.ShopInventory[i].PC.Default.InventoryType).Default.UnlockedByAchievement!=-1 )
Link.ShopInventory[i].bDLCLocked = 2; // Special hack for dwarf axe.
else Link.ShopInventory[i].bDLCLocked = 1;
continue;
}
d = class<KFWeapon>(Link.ShopInventory[i].PC.Default.InventoryType).Default.UnlockedByAchievement;
if( Achievements[d].bCompleted==1 )
Link.ShopInventory[i].bDLCLocked = 0;
else Link.ShopInventory[i].bDLCLocked = 2;
}
for ( i = 0; i < Achievements.Length; i++ )
GetAchievementDescription(Achievements[i].SteamName, Default.Achievements[i].DisplayName, Default.Achievements[i].Description);
Destroy();
}
defaultproperties
{
RemoteRole=ROLE_None
LifeSpan=10.000000
}

View file

@ -0,0 +1,11 @@
class SRTab_Base extends MidGamePanel
abstract;
defaultproperties
{
PropagateVisibility=False
WinTop=0.125000
WinLeft=0.250000
WinWidth=0.500000
WinHeight=0.750000
}

View file

@ -0,0 +1,217 @@
class SRTab_MidGameHelp extends SRTab_Base;
var bool bReceivedGameClass;
var automated GUISectionBackground sb_GameDesc, sb_Hints;
var automated GUIScrollTextBox GameDescriptionBox, HintsBox;
var automated GUILabel HintCountLabel;
var automated GUIButton PrevHintButton, NextHintButton;
var class<GameInfo> GameClass;
var array<string> AllGameHints;
var int CurrentHintIndex;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
// Init localized
sb_GameDesc.Caption = Class'KFTab_MidGameHelp'.Default.sb_GameDesc.Caption;
sb_Hints.Caption = Class'KFTab_MidGameHelp'.Default.sb_Hints.Caption;
PrevHintButton.Caption = Class'KFTab_MidGameHelp'.Default.PrevHintButton.Caption;
NextHintButton.Caption = Class'KFTab_MidGameHelp'.Default.NextHintButton.Caption;
Super.Initcomponent(MyController, MyOwner);
sb_GameDesc.ManageComponent(GameDescriptionBox);
sb_Hints.ManageComponent(HintsBox);
PrevHintButton.bBoundToParent=false; PrevHintButton.bScaleToParent=false;
NextHintButton.bBoundToParent=false; NextHintButton.bScaleToParent=false;
HintCountLabel.bBoundToParent=false; HintCountLabel.bScaleToParent=false;
}
function ShowPanel(bool bShow)
{
Super.ShowPanel(bShow);
if (bShow && !bReceivedGameClass)
{
SetTimer(1.0, true);
Timer();
}
}
function Timer()
{
local PlayerController PC;
local int i;
PC = PlayerOwner();
if (PC != None && PC.GameReplicationInfo != None && PC.GameReplicationInfo.GameClass != "")
{
GameClass = class<GameInfo>(DynamicLoadObject(PC.GameReplicationInfo.GameClass, class'Class'));
if (GameClass != None)
{
//get game description and hints from game class
GameDescriptionBox.SetContent(GameClass.default.Description);
AllGameHints = GameClass.static.GetAllLoadHints();
if (AllGameHints.length > 0)
{
for (i = 0; i < AllGameHints.length; i++)
{
AllGameHints[i] = GameClass.static.ParseLoadingHint(AllGameHints[i], PC, HintsBox.Style.FontColors[HintsBox.MenuState]);
if (AllGameHints[i] == "")
{
AllGameHints.Remove(i, 1);
i--;
}
}
HintsBox.SetContent(AllGameHints[CurrentHintIndex]);
HintCountLabel.Caption = string(CurrentHintIndex + 1) @ "/" @ string(AllGameHints.length);
EnableComponent(PrevHintButton);
EnableComponent(NextHintButton);
}
KillTimer();
bReceivedGameClass = true;
}
}
}
function bool ButtonClicked(GUIComponent Sender)
{
if (Sender == PrevHintButton)
{
CurrentHintIndex--;
if (CurrentHintIndex < 0)
CurrentHintIndex = AllGameHints.length - 1;
}
else if (Sender == NextHintButton)
{
CurrentHintIndex++;
if (CurrentHintIndex >= AllGameHints.length)
CurrentHintIndex = 0;
}
HintsBox.SetContent(AllGameHints[CurrentHintIndex]);
HintCountLabel.Caption = string(CurrentHintIndex + 1) @ "/" @ string(AllGameHints.length);
return true;
}
function bool FixUp(Canvas C)
{
local float t,h,l,w,xl;
h = 20;
t = sb_Hints.ActualTop() + sb_Hints.ActualHeight() - 27;
PrevHintButton.WinLeft = sb_Hints.ActualLeft() + 40;
PrevHintButton.WinTop = t;
PrevHintButton.WinHeight=h;
NextHintButton.WinLeft = sb_Hints.ActualLeft() + sb_Hints.ActualWidth() - 40 - NextHintButton.ActualWidth();
NextHintButton.WinTop = t;
NextHintButton.WinHeight=h;
l = PrevHintButton.ActualLeft() + PrevHintButton.ActualWidth();
w = NextHintButton.ActualLeft() - L;
XL = HintCountLabel.ActualWidth();
l = l + (w/2) - (xl/2);
HintCountLabel.WinLeft=l;
HintCountLabel.WinTop=t;
HintCountLabel.WinWidth = xl;
HintCountLabel.WinHeight=h;
return false;
}
defaultproperties
{
Begin Object Class=AltSectionBackground Name=sbGameDesc
bFillClient=True
WinTop=0.020438
WinLeft=0.023625
WinWidth=0.944875
WinHeight=0.455783
bBoundToParent=True
bScaleToParent=True
OnPreDraw=sbGameDesc.InternalPreDraw
End Object
sb_GameDesc=AltSectionBackground'ServerPerks.SRTab_MidGameHelp.sbGameDesc'
Begin Object Class=AltSectionBackground Name=sbHints
bFillClient=True
WinTop=0.482921
WinLeft=0.023625
WinWidth=0.944875
WinHeight=0.390000
bBoundToParent=True
bScaleToParent=True
OnPreDraw=sbHints.InternalPreDraw
End Object
sb_Hints=AltSectionBackground'ServerPerks.SRTab_MidGameHelp.sbHints'
Begin Object Class=GUIScrollTextBox Name=InfoText
bNoTeletype=True
CharDelay=0.002500
EOLDelay=0.000000
TextAlign=TXTA_Center
OnCreateComponent=InfoText.InternalOnCreateComponent
WinTop=0.203750
WinHeight=0.316016
bBoundToParent=True
bScaleToParent=True
bNeverFocus=True
End Object
GameDescriptionBox=GUIScrollTextBox'ServerPerks.SRTab_MidGameHelp.InfoText'
Begin Object Class=GUIScrollTextBox Name=HintText
bNoTeletype=True
CharDelay=0.002500
EOLDelay=0.000000
TextAlign=TXTA_Center
OnCreateComponent=HintText.InternalOnCreateComponent
WinTop=0.653750
WinHeight=0.266016
bBoundToParent=True
bScaleToParent=True
bNeverFocus=True
End Object
HintsBox=GUIScrollTextBox'ServerPerks.SRTab_MidGameHelp.HintText'
Begin Object Class=GUILabel Name=HintCount
TextAlign=TXTA_Center
TextColor=(B=255,G=255,R=255)
WinTop=0.900000
WinLeft=0.300000
WinWidth=0.400000
WinHeight=32.000000
End Object
HintCountLabel=GUILabel'ServerPerks.SRTab_MidGameHelp.HintCount'
Begin Object Class=GUIButton Name=PrevHint
bAutoSize=True
WinTop=0.750000
WinLeft=0.131500
WinWidth=0.226801
WinHeight=0.042125
TabOrder=0
OnClick=SRTab_MidGameHelp.ButtonClicked
OnKeyEvent=PrevHint.InternalOnKeyEvent
End Object
PrevHintButton=GUIButton'ServerPerks.SRTab_MidGameHelp.PrevHint'
Begin Object Class=GUIButton Name=NextHint
bAutoSize=True
WinTop=0.750000
WinLeft=0.698425
WinWidth=0.159469
WinHeight=0.042125
TabOrder=1
OnClick=SRTab_MidGameHelp.ButtonClicked
OnKeyEvent=NextHint.InternalOnKeyEvent
End Object
NextHintButton=GUIButton'ServerPerks.SRTab_MidGameHelp.NextHint'
OnPreDraw=SRTab_MidGameHelp.FixUp
}

View file

@ -0,0 +1,157 @@
class SRTab_MidGamePerks extends SRTab_Base;
// begin KFTab_MidGamePerks
var automated GUISectionBackground i_BGPerks;
var automated SRPerkSelectListBox lb_PerkSelect;
var automated GUISectionBackground i_BGPerkEffects;
var automated GUIScrollTextBox lb_PerkEffects;
var automated GUISectionBackground i_BGPerkNextLevel;
var automated SRPerkProgressListBox lb_PerkProgress;
var automated GUIButton b_Save;
// end KFTab_MidGamePerks
var localized string NextInfoStr,PleaseWaitStr;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
// Init localized
i_BGPerks.Caption = Class'KFTab_MidGamePerks'.Default.i_BGPerks.Caption;
i_BGPerkEffects.Caption = Class'KFTab_MidGamePerks'.Default.i_BGPerkEffects.Caption;
i_BGPerkNextLevel.Caption = Class'KFTab_MidGamePerks'.Default.i_BGPerkNextLevel.Caption;
b_Save.Caption = Class'KFTab_MidGamePerks'.Default.b_Save.Caption;
b_Save.Hint = Class'KFTab_MidGamePerks'.Default.b_Save.Hint;
Super.InitComponent(MyController, MyOwner);
lb_PerkSelect.List.OnChange = OnPerkSelected;
}
function ShowPanel(bool bShow)
{
Super.ShowPanel(bShow);
if ( bShow )
{
if ( Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner())!=none )
{
// Initialize the List
lb_PerkSelect.List.InitList(None);
lb_PerkProgress.List.InitList();
}
}
}
function OnPerkSelected(GUIComponent Sender)
{
local ClientPerkRepLink ST;
local byte Idx;
ST = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( ST==None || ST.CachePerks.Length==0 )
{
if( ST!=None )
ST.ServerRequestPerks();
lb_PerkEffects.SetContent(PleaseWaitStr);
}
else
{
Idx = lb_PerkSelect.GetIndex();
if( ST.CachePerks[Idx].CurrentLevel==0 )
lb_PerkEffects.SetContent(ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(0,1));
else if( ST.CachePerks[Idx].CurrentLevel==ST.MaximumLevel )
lb_PerkEffects.SetContent(ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel-1,1));
else lb_PerkEffects.SetContent(ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel-1,1)$NextInfoStr$ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel,1));
lb_PerkProgress.List.PerkChanged(None, Idx);
}
}
function bool OnSaveButtonClicked(GUIComponent Sender)
{
local ClientPerkRepLink ST;
ST = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( ST!=None && lb_PerkSelect.GetIndex()>=0 )
ST.ServerSelectPerk(ST.CachePerks[lb_PerkSelect.GetIndex()].PerkClass);
return true;
}
defaultproperties
{
Begin Object Class=GUISectionBackground Name=BGPerks
bFillClient=True
WinTop=0.012063
WinLeft=0.019240
WinWidth=0.457166
WinHeight=0.796032
OnPreDraw=BGPerks.InternalPreDraw
End Object
i_BGPerks=GUISectionBackground'ServerPerks.SRTab_MidGamePerks.BGPerks'
Begin Object Class=SRPerkSelectListBox Name=PerkSelectList
OnCreateComponent=PerkSelectList.InternalOnCreateComponent
WinTop=0.057760
WinLeft=0.029240
WinWidth=0.437166
WinHeight=0.742836
End Object
lb_PerkSelect=SRPerkSelectListBox'ServerPerks.SRTab_MidGamePerks.PerkSelectList'
Begin Object Class=GUISectionBackground Name=BGPerkEffects
bFillClient=True
WinTop=0.012063
WinLeft=0.486700
WinWidth=0.491566
WinHeight=0.366816
OnPreDraw=BGPerkEffects.InternalPreDraw
End Object
i_BGPerkEffects=GUISectionBackground'ServerPerks.SRTab_MidGamePerks.BGPerkEffects'
Begin Object Class=GUIScrollTextBox Name=PerkEffectsScroll
CharDelay=0.002500
EOLDelay=0.100000
OnCreateComponent=PerkEffectsScroll.InternalOnCreateComponent
WinTop=0.057760
WinLeft=0.500554
WinWidth=0.465143
WinHeight=0.313477
TabOrder=9
End Object
lb_PerkEffects=GUIScrollTextBox'ServerPerks.SRTab_MidGamePerks.PerkEffectsScroll'
Begin Object Class=GUISectionBackground Name=BGPerksNextLevel
bFillClient=True
WinTop=0.392889
WinLeft=0.486700
WinWidth=0.490282
WinHeight=0.415466
OnPreDraw=BGPerksNextLevel.InternalPreDraw
End Object
i_BGPerkNextLevel=GUISectionBackground'ServerPerks.SRTab_MidGamePerks.BGPerksNextLevel'
Begin Object Class=SRPerkProgressListBox Name=PerkProgressList
OnCreateComponent=PerkProgressList.InternalOnCreateComponent
WinTop=0.476850
WinLeft=0.499269
WinWidth=0.463858
WinHeight=0.341256
End Object
lb_PerkProgress=SRPerkProgressListBox'ServerPerks.SRTab_MidGamePerks.PerkProgressList'
Begin Object Class=GUIButton Name=SaveButton
WinTop=0.822807
WinLeft=0.302670
WinWidth=0.363829
WinHeight=0.042757
TabOrder=2
bBoundToParent=True
OnClick=SRTab_MidGamePerks.OnSaveButtonClicked
OnKeyEvent=SaveButton.InternalOnKeyEvent
End Object
b_Save=GUIButton'ServerPerks.SRTab_MidGamePerks.SaveButton'
NextInfoStr="||Next level effects:|"
PleaseWaitStr="Please wait while your client is loading the perks..."
}

View file

@ -0,0 +1,42 @@
class SRTab_MidGameStats extends SRTab_Base;
var automated GUISectionBackground i_BGPerks;
var automated SRStatListBox lb_PerkSelect;
function ShowPanel(bool bShow)
{
local ClientPerkRepLink L;
super.ShowPanel(bShow);
if ( bShow )
{
L = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( L!=None )
lb_PerkSelect.List.InitList(L);
}
}
defaultproperties
{
Begin Object Class=GUISectionBackground Name=BGPerks
bFillClient=True
Caption="Stats"
WinTop=0.012063
WinLeft=0.019240
WinWidth=0.961520
WinHeight=0.796032
OnPreDraw=BGPerks.InternalPreDraw
End Object
i_BGPerks=GUISectionBackground'ServerPerks.SRTab_MidGameStats.BGPerks'
Begin Object Class=SRStatListBox Name=StatSelectList
OnCreateComponent=StatSelectList.InternalOnCreateComponent
WinTop=0.057760
WinLeft=0.029240
WinWidth=0.941520
WinHeight=0.742836
End Object
lb_PerkSelect=SRStatListBox'ServerPerks.SRTab_MidGameStats.StatSelectList'
}

View file

@ -0,0 +1,536 @@
class SRTab_MidGameVoiceChat extends SRTab_Base;
var array<UT2K4Tab_MidGameVoiceChat.ChatItem> ChatList;
var automated GUISectionBackground sb_Players, sb_Specs, sb_Options;
var automated GUIListBox lb_Players, lb_Specs;
var automated GUIList li_Players, li_Specs;
var automated moCheckbox ch_NoVoiceChat, ch_NoSpeech, ch_NoText, ch_Ban;
var() int SelectIndex;
var() editconst bool bTeamGame;
function GameReplicationInfo GRI()
{
return PlayerOwner().GameReplicationInfo;
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
// Init localizations
sb_Players.Caption = Class'UT2K4Tab_MidGameVoiceChat'.Default.sb_Players.Caption;
sb_Specs.Caption = Class'UT2K4Tab_MidGameVoiceChat'.Default.sb_Specs.Caption;
sb_Options.Caption = Class'UT2K4Tab_MidGameVoiceChat'.Default.sb_Options.Caption;
ch_NoVoiceChat.Caption = Class'UT2K4Tab_MidGameVoiceChat'.Default.ch_NoVoiceChat.Caption;
ch_NoVoiceChat.Hint = Class'UT2K4Tab_MidGameVoiceChat'.Default.ch_NoVoiceChat.Hint;
ch_NoSpeech.Caption = Class'UT2K4Tab_MidGameVoiceChat'.Default.ch_NoSpeech.Caption;
ch_NoSpeech.Hint = Class'UT2K4Tab_MidGameVoiceChat'.Default.ch_NoSpeech.Hint;
ch_NoText.Caption = Class'UT2K4Tab_MidGameVoiceChat'.Default.ch_NoText.Caption;
ch_NoText.Hint = Class'UT2K4Tab_MidGameVoiceChat'.Default.ch_NoText.Hint;
ch_Ban.Caption = Class'UT2K4Tab_MidGameVoiceChat'.Default.ch_Ban.Caption;
ch_Ban.Hint = Class'UT2K4Tab_MidGameVoiceChat'.Default.ch_Ban.Hint;
Super.InitComponent(MyController, MyOwner);
// Tie lists together with buttons
li_Players = lb_Players.List;
li_Specs = lb_Specs.List;
li_Players.bInitializeList = false;
li_Specs.bInitializeList = false;
sb_Players.ManageComponent( lb_Players );
sb_Specs.ManageComponent( lb_Specs );
sb_Options.ManageComponent( ch_NoText );
sb_Options.ManageComponent( ch_NoSpeech );
sb_Options.ManageComponent( ch_NoVoiceChat );
sb_Options.ManageComponent( ch_Ban );
AssociateButtons();
}
function ShowPanel( bool bShow )
{
Super.ShowPanel(bShow);
if ( !bShow )
{
ClearIndexes(None);
SaveRestrictions();
}
}
event Closed( GUIComponent Sender, bool bCancelled )
{
SaveRestrictions();
Super.Closed(Sender,bCancelled);
}
// =====================================================================================================================
// =====================================================================================================================
// GUI Interface
// =====================================================================================================================
// =====================================================================================================================
function bool PreDraw(Canvas Canvas)
{
if ( GRI() != None )
{
bTeamGame = GRI().bTeamGame;
FillPlayerLists();
}
return false;
}
// Called when an player's name is clicked on
function ListChange( GUIComponent Sender )
{
local int ID;
local GUIList List;
List = GUIListBox(Sender).List;
if ( List == None )
return;
ClearIndexes( List );
// grab the associated PlayerID from the selected player
id = int(List.GetExtra());
if ( PlayerIDIsMine(id) )
{
SelectedSelf();
return;
}
SelectIndex = FindChatListIndex(id);
LoadRestrictions(SelectIndex);
}
function InternalOnChange(GUIComponent Sender)
{
local bool bResult;
if ( !ValidIndex(SelectIndex) )
return;
bResult = moCheckbox(Sender).IsChecked();
ChatList[SelectIndex].bDirty = true;
switch (Sender)
{
case ch_NoText:
ChatList[SelectIndex].bNoText = bResult;
break;
case ch_NoSpeech:
ChatList[SelectIndex].bNoSpeech = bResult;
break;
case ch_NoVoiceChat:
ChatList[SelectIndex].bNoVoice = bResult;
break;
case ch_Ban:
ChatList[SelectIndex].bBanned = bResult;
break;
}
if ( ChatList[SelectIndex].bDirty && ApplyRestriction(SelectIndex) )
{
ModifiedChatRestriction(Self, ChatList[SelectIndex].PlayerID);
ChatList[SelectIndex].bDirty = False;
}
}
// =====================================================================================================================
// =====================================================================================================================
// Implementation
// =====================================================================================================================
// =====================================================================================================================
// Get a list of all players, and put them into the appropriate list
function FillPlayerLists()
{
local string idx;
if ( GRI() == None )
return;
// if an item was selected, remember the selected PlayerID while we clear and refill the lists
if ( li_Players.IsValid() )
idx = li_Players.GetExtra();
else if ( li_Specs.IsValid() )
idx = "";
// Disable all list notification while we're clearing and refilling the lists
li_Players.bNotify = false;
li_Specs.bNotify = false;
ClearLists();
PopulateLists( GRI() );
// if we had a PlayerID selected, attempt to reselect that PlayerID in any list
if ( idx != "" )
{
if ( li_Players.Find(idx,false,true) != "" )
{
if ( !PlayerIDIsMine(idx) )
li_Players.CheckLinkedObjects(li_Players);
}
else if ( li_Specs.Find(idx,false,true) != "" )
{
if ( !PlayerIDIsMine(idx) )
li_Specs.CheckLinkedObjects(li_Specs);
}
}
li_Players.bNotify = true;
li_Specs.bNotify = true;
}
function PopulateLists(GameReplicationInfo GRI)
{
local int i;
local PlayerReplicationInfo PRI;
for ( i = 0; i < GRI.PRIArray.Length; i++ )
{
PRI = GRI.PRIArray[i];
if ( PRI == None || PRI.bBot || xPlayerReplicationInfo(PRI) == none )
continue;
// If this is the first time seeing this playerid, request the ban/ignore info from our ChatManager
if ( FindChatListIndex(PRI.PlayerID) == -1 )
AddPlayerInfo(PRI.PlayerID);
if ( PRI.bOnlySpectator )
li_Specs.Add(PRI.PlayerName,,string(PRI.PlayerID));
else li_Players.Add( PRI.PlayerName,,string(PRI.PlayerID) );
}
}
// When a list item is selected, clear the indexes of the other lists
function ClearIndexes( GUIList List )
{
if ( List != li_Players)
li_Players.SilentSetIndex(-1);
if ( List != li_Specs )
li_Specs.SilentSetIndex(-1);
if ( List == None )
SelectedSelf();
}
// =====================================================================================================================
// =====================================================================================================================
// Chat Manager Interface
// =====================================================================================================================
// =====================================================================================================================
// Set the checkboxes to the values associated with the given player
function LoadRestrictions(int i)
{
if ( !ValidIndex(i) )
{
ch_NoText.SetComponentValue(False, True);
ch_NoSpeech.SetComponentValue(False, True);
ch_NoVoiceChat.SetComponentValue(False, True);
ch_Ban.SetComponentValue(False, True);
}
else
{
ch_NoText.SetComponentValue(ChatList[i].bNoText, True);
ch_NoSpeech.SetComponentValue(ChatList[i].bNoSpeech, True);
ch_NoVoiceChat.SetComponentValue(ChatList[i].bNoVoice, True);
ch_Ban.SetComponentValue(ChatList[i].bBanned, True);
}
}
// Called when a new playerID is found while filling the lists
// Request stored chat restrictions for this PlayerID from the ChatManager
function int AddPlayerInfo(int PlayerID)
{
local int i;
local PlayerController PC;
local byte Restriction;
PC = PlayerOwner();
if ( PC.ChatManager == None )
return -1;
// Verify that we don't already have this player ID in the list
i = FindChatListIndex( PlayerID );
if ( i == -1 )
{
i = ChatList.Length;
ChatList.Length = i+1;
}
ChatList[i].PlayerID = PlayerID;
// Query the ChatManager for the settings for this player
Restriction = PC.ChatManager.GetPlayerRestriction(PlayerID);
UnpackRestriction(i, Restriction);
return i;
}
function PackRestriction(int i, out byte Restriction)
{
Restriction = 0;
if ( ValidIndex(i) )
{
if ( ChatList[i].bNoText )
Restriction = Restriction | 1;
if ( ChatList[i].bNoSpeech )
Restriction = Restriction | 2;
if ( ChatList[i].bNoVoice )
Restriction = Restriction | 4;
if ( ChatList[i].bBanned )
Restriction = Restriction | 8;
}
}
function UnpackRestriction(int i, byte Restriction)
{
if ( ValidIndex(i) )
{
ChatList[i].bNoText = bool(Restriction & 1);
ChatList[i].bNoSpeech = bool(Restriction & 2);
ChatList[i].bNoVoice = bool(Restriction & 4);
ChatList[i].bBanned = bool(Restriction & 8);
Chatlist[i].bDirty = false;
}
}
function bool ApplyRestriction(int i)
{
local byte Restriction;
// Send restrictions to player's chat manager
if ( ValidIndex(i) )
{
PackRestriction(i, Restriction);
return PlayerOwner().ChatBan(ChatList[i].PlayerID, Restriction);
}
return false;
}
function SaveRestrictions()
{
local int i;
for ( i = 0; i < ChatList.Length; i++ )
{
if ( Chatlist[i].bDirty && ApplyRestriction(i) )
{
ModifiedChatRestriction(Self, Chatlist[i].PlayerID);
Chatlist[i].bDirty = false;
}
}
}
function ResetRestrictions()
{
local int i;
local byte Restriction;
for ( i = 0; i < ChatList.Length; i++ )
{
PackRestriction(i, Restriction);
if ( Restriction != 0 )
PlayerOwner().ChatBan(ChatList[i].PlayerID, 0);
}
PlayerOwner().ChatManager.ClearConfig();
}
function UpdateChatRestriction( int PlayerID )
{
local int i;
Super.UpdateChatRestriction(PlayerID);
i = FindChatListIndex(PlayerID);
if ( ValidIndex(i) )
UnpackRestriction( i, PlayerOwner().ChatManager.GetPlayerRestriction(PlayerID) );
}
// =====================================================================================================================
// =====================================================================================================================
// Utility / Helper functions
// =====================================================================================================================
// =====================================================================================================================
function ClearLists()
{
if ( li_Players.ItemCount > 0 )
li_Players.Clear();
if ( li_Specs.ItemCount > 0 )
li_Specs.Clear();
}
// Disable/enable these components based on whether or not a list has a valid index
function AssociateButtons()
{
LinkList(li_Players);
LinkList(li_Specs);
}
function LinkList( GUIList List )
{
if ( List == None )
return;
List.AddLinkObject( ch_NoVoiceChat );
List.AddLinkObject( ch_NoSpeech );
List.AddLinkObject( ch_NoText );
List.AddLinkObject( ch_Ban );
}
function int FindChatListIndex(int PlayerID)
{
local int i;
for ( i = 0; i < ChatList.Length; i++ )
if ( PlayerID == ChatList[i].PlayerID )
return i;
return -1;
}
function bool ValidIndex(int i)
{
return i >= 0 && i < ChatList.Length;
}
function SelectedSelf()
{
ch_NoText.SetComponentValue(False, True);
ch_NoSpeech.SetComponentValue(False, True);
ch_NoVoiceChat.SetComponentValue(False, True);
ch_Ban.SetComponentValue(False, True);
DisableComponent(ch_NoText);
DisableComponent(ch_NoSpeech);
DisableComponent(ch_NoVoiceChat);
DisableComponent(ch_Ban);
}
defaultproperties
{
Begin Object Class=AltSectionBackground Name=PlayersBackground
LeftPadding=0.000000
RightPadding=0.000000
TopPadding=0.000000
BottomPadding=0.000000
WinTop=0.030000
WinLeft=0.019250
WinWidth=0.462019
WinHeight=0.840000
bBoundToParent=True
bScaleToParent=True
OnPreDraw=PlayersBackground.InternalPreDraw
End Object
sb_Players=AltSectionBackground'ServerPerks.SRTab_MidGameVoiceChat.PlayersBackground'
Begin Object Class=AltSectionBackground Name=SpecBackground
LeftPadding=0.000000
RightPadding=0.000000
TopPadding=0.000000
BottomPadding=0.000000
WinTop=0.030325
WinLeft=0.512544
WinWidth=0.462019
WinHeight=0.468385
bBoundToParent=True
bScaleToParent=True
OnPreDraw=SpecBackground.InternalPreDraw
End Object
sb_Specs=AltSectionBackground'ServerPerks.SRTab_MidGameVoiceChat.SpecBackground'
Begin Object Class=AltSectionBackground Name=OptionBackground
TopPadding=0.040000
BottomPadding=0.000000
WinTop=0.508063
WinLeft=0.512544
WinWidth=0.462019
WinHeight=0.362000
bBoundToParent=True
bScaleToParent=True
OnPreDraw=OptionBackground.InternalPreDraw
End Object
sb_Options=AltSectionBackground'ServerPerks.SRTab_MidGameVoiceChat.OptionBackground'
Begin Object Class=GUIListBox Name=PlayersList
bInitializeList=False
OnCreateComponent=PlayersList.InternalOnCreateComponent
WinTop=0.041667
WinLeft=0.056250
WinWidth=0.431250
WinHeight=0.760000
TabOrder=0
OnChange=SRTab_MidGameVoiceChat.ListChange
End Object
lb_Players=GUIListBox'ServerPerks.SRTab_MidGameVoiceChat.PlayersList'
Begin Object Class=GUIListBox Name=SpecList
bInitializeList=False
OnCreateComponent=SpecList.InternalOnCreateComponent
WinTop=0.041667
WinLeft=0.531250
WinWidth=0.431250
WinHeight=0.518750
TabOrder=1
OnChange=SRTab_MidGameVoiceChat.ListChange
End Object
lb_Specs=GUIListBox'ServerPerks.SRTab_MidGameVoiceChat.SpecList'
Begin Object Class=moCheckBox Name=NoVoiceChat
OnCreateComponent=NoVoiceChat.InternalOnCreateComponent
WinTop=0.750178
WinLeft=0.647884
WinWidth=0.338524
WinHeight=0.049840
TabOrder=4
OnChange=SRTab_MidGameVoiceChat.InternalOnChange
End Object
ch_NoVoiceChat=moCheckBox'ServerPerks.SRTab_MidGameVoiceChat.NoVoiceChat'
Begin Object Class=moCheckBox Name=NOSPEECH
OnCreateComponent=NOSPEECH.InternalOnCreateComponent
WinTop=0.685424
WinLeft=0.647884
WinWidth=0.338524
WinHeight=0.049840
TabOrder=3
OnChange=SRTab_MidGameVoiceChat.InternalOnChange
End Object
ch_NoSpeech=moCheckBox'ServerPerks.SRTab_MidGameVoiceChat.NOSPEECH'
Begin Object Class=moCheckBox Name=NOTEXT
OnCreateComponent=NOTEXT.InternalOnCreateComponent
WinTop=0.620670
WinLeft=0.647884
WinWidth=0.338524
WinHeight=0.049840
TabOrder=2
OnChange=SRTab_MidGameVoiceChat.InternalOnChange
End Object
ch_NoText=moCheckBox'ServerPerks.SRTab_MidGameVoiceChat.NOTEXT'
Begin Object Class=moCheckBox Name=BanPlayer
OnCreateComponent=BanPlayer.InternalOnCreateComponent
WinTop=0.814932
WinLeft=0.647884
WinWidth=0.338524
WinHeight=0.049840
TabOrder=5
OnChange=SRTab_MidGameVoiceChat.InternalOnChange
End Object
ch_Ban=moCheckBox'ServerPerks.SRTab_MidGameVoiceChat.BanPlayer'
OnPreDraw=SRTab_MidGameVoiceChat.PreDraw
}

View file

@ -0,0 +1,181 @@
class SRTab_Profile extends KFTab_Profile;
var string ChangedCharacter,ClientRepChar;
function bool InternalDraw(Canvas canvas)
{
local PlayerController PC;
PC = PlayerOwner();
if( PC.PlayerReplicationInfo!=None && ClientRepChar!=PC.PlayerReplicationInfo.CharacterName )
SetPlayerRec(); // Delayed replication setup.
return Super.InternalDraw(Canvas);
}
function UpdateScroll()
{
if( PlayerRec.TextName!="" )
lb_Scroll.SetContent(PlayerRec.TextName);
else Super.UpdateScroll();
}
function InternalOnLoadINI(GUIComponent Sender, string s)
{
ChangedCharacter = "";
if ( Sender == i_Portrait )
SetPlayerRec();
}
function bool PickModel(GUIComponent Sender)
{
if ( Controller.OpenMenu(string(Class'SRModelSelect'), PlayerRec.DefaultName, Eval(Controller.CtrlPressed, PlayerRec.Race, "")) )
{
Controller.ActivePage.OnClose = ModelSelectClosed;
}
return true;
}
function SetPlayerRec()
{
local PlayerController PC;
PC = PlayerOwner();
if( ChangedCharacter!="" )
sChar = ChangedCharacter;
else if( PC.PlayerReplicationInfo!=None )
sChar = PC.PlayerReplicationInfo.CharacterName;
if( PC.PlayerReplicationInfo!=None )
ClientRepChar = PC.PlayerReplicationInfo.CharacterName;
PlayerRec = Class'xUtil'.Static.FindPlayerRecord(sChar);
UpdateScroll();
ShowSpinnyDude();
}
function ShowPanel(bool bShow)
{
local ClientPerkRepLink S;
if ( bShow )
{
if ( bInit )
{
bRenderDude = True;
bInit = False;
}
if ( PlayerOwner() != none )
{
S = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( S!=none )
{
// Initialize the List
lb_PerkSelect.List.InitList(None);
lb_PerkProgress.List.InitList();
}
}
}
lb_PerkSelect.SetPosition(i_BGPerks.WinLeft + 6.0 / float(Controller.ResX),
i_BGPerks.WinTop + 38.0 / float(Controller.ResY),
i_BGPerks.WinWidth - 10.0 / float(Controller.ResX),
i_BGPerks.WinHeight - 35.0 / float(Controller.ResY),
true);
SetVisibility(bShow);
}
function SaveSettings()
{
local PlayerController PC;
local ClientPerkRepLink S;
PC = PlayerOwner();
S = Class'ClientPerkRepLink'.Static.FindStats(PC);
if ( ChangedCharacter!="" )
{
if( S!=None )
S.SelectedCharacter(ChangedCharacter);
else
{
PC.ConsoleCommand("ChangeCharacter"@ChangedCharacter);
if ( !PC.IsA('xPlayer') )
PC.UpdateURL("Character", ChangedCharacter, True);
if ( PlayerRec.Sex ~= "Female" )
PC.UpdateURL("Sex", "F", True);
else PC.UpdateURL("Sex", "M", True);
}
ChangedCharacter = "";
}
if ( lb_PerkSelect.GetIndex()>=0 && S!=None )
S.ServerSelectPerk(S.CachePerks[lb_PerkSelect.GetIndex()].PerkClass);
}
function ModelSelectClosed( optional bool bCancelled )
{
local string str;
if ( bCancelled )
return;
str = Controller.ActivePage.GetDataString();
if ( str != "" )
{
ChangedCharacter = str;
SetPlayerRec();
}
}
function OnPerkSelected(GUIComponent Sender)
{
local ClientPerkRepLink ST;
local byte Idx;
local string S;
ST = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if ( ST==None || ST.CachePerks.Length==0 )
{
if( ST!=None )
ST.ServerRequestPerks();
lb_PerkEffects.SetContent("Please wait while your client is loading the perks...");
}
else
{
Idx = lb_PerkSelect.GetIndex();
if( ST.CachePerks[Idx].CurrentLevel==0 )
S = ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(0,1);
else if( ST.CachePerks[Idx].CurrentLevel==ST.MaximumLevel )
S = ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel-1,1);
else S = ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel-1,1)$Class'SRTab_MidGamePerks'.Default.NextInfoStr$ST.CachePerks[Idx].PerkClass.Static.GetVetInfoText(ST.CachePerks[Idx].CurrentLevel,1);
lb_PerkEffects.SetContent(S);
lb_PerkProgress.List.PerkChanged(KFStatsAndAchievements, Idx);
}
}
defaultproperties
{
Begin Object Class=SRPerkSelectListBox Name=PerkSelectList
OnCreateComponent=PerkSelectList.InternalOnCreateComponent
WinTop=0.082969
WinLeft=0.323418
WinWidth=0.318980
WinHeight=0.654653
End Object
lb_PerkSelect=SRPerkSelectListBox'ServerPerks.SRTab_Profile.PerkSelectList'
Begin Object Class=SRPerkProgressListBox Name=PerkProgressList
OnCreateComponent=PerkProgressList.InternalOnCreateComponent
WinTop=0.439668
WinLeft=0.670121
WinWidth=0.319980
WinHeight=0.292235
End Object
lb_PerkProgress=SRPerkProgressListBox'ServerPerks.SRTab_Profile.PerkProgressList'
}

View file

@ -0,0 +1,217 @@
class SRTab_ServerNews extends SRTab_Base;
var automated GUIButton b_Prev,b_Next,b_Reload;
var automated GUISectionBackground i_BGSec;
var automated GUIScrollTextBox lb_Text;
var automated GUIHTMLTextBox HTMLText;
var byte Stage;
var SRBufferedTCPLink Link;
var array<string> BrowseHistory;
var int CurrentIndex;
var string NextHistory;
var bool bAddHistory,bSkipHistoryChange;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local PlayerController PC;
Super.InitComponent(MyController, MyOwner);
CheckButtons();
PC = PlayerOwner();
if( PC.Level.GRI!=None )
SetNewsText(Repl(PC.Level.GRI.MessageOfTheDay,"|","<BR>"));
SetTimer(0.25,true);
Timer();
}
function Timer()
{
switch( Stage )
{
case 0:
FirstPass();
break;
case 1:
SecondPass();
break;
}
}
final function FirstPass()
{
local ClientPerkRepLink L;
L = Class'ClientPerkRepLink'.Static.FindStats(PlayerOwner());
if( L==None || !L.bReceivedURL )
return;
if( L.ServerWebSite=="" )
{
BrowseHistory.Length = 0;
KillTimer();
}
else
{
Link = PlayerOwner().Spawn(class'SRBufferedTCPLink');
Link.StartBuffering(L.ServerWebSite);
BrowseHistory.Length = 1;
BrowseHistory[0] = L.ServerWebSite;
CurrentIndex = 0;
++Stage;
CheckButtons();
}
}
final function SecondPass()
{
if( Link.bHasError )
SetNewsText("Error when connecting to news page:| -"$Link.ErrorName);
else if( Link.bHasData )
SetNewsText(Link.InputBuffer);
else return; // Waiting.
Link.DestroyLink();
Link = none;
KillTimer();
}
final function SetNewsText( string S )
{
if( bAddHistory )
{
++CurrentIndex;
BrowseHistory.Length = CurrentIndex+1;
BrowseHistory[CurrentIndex] = NextHistory;
}
HTMLText.SetContents(S);
if( HTMLText.TitleString!="" )
i_BGSec.Caption = HTMLText.TitleString;
CheckButtons();
}
function SwitchPage( string NewURL )
{
if( Link!=None )
Link.DestroyLink();
Link = PlayerOwner().Spawn(class'SRBufferedTCPLink');
Link.StartBuffering(NewURL);
if( bSkipHistoryChange )
bAddHistory = false;
else
{
NextHistory = NewURL;
bAddHistory = true;
}
SetTimer(0.25,true);
}
final function GoToHistory( int Move )
{
CurrentIndex = Clamp(CurrentIndex+Move,0,BrowseHistory.Length-1);
bSkipHistoryChange = true;
SwitchPage(BrowseHistory[CurrentIndex]);
bSkipHistoryChange = false;
CheckButtons();
}
final function CheckButtons()
{
if( BrowseHistory.Length==0 )
{
DisableComponent(b_Prev);
DisableComponent(b_Next);
DisableComponent(b_Reload);
return;
}
EnableComponent(b_Reload);
if( CurrentIndex<=0 )
DisableComponent(b_Prev);
else EnableComponent(b_Prev);
if( CurrentIndex>=(BrowseHistory.Length-1) )
DisableComponent(b_Next);
else EnableComponent(b_Next);
}
function bool ButtonClicked(GUIComponent Sender)
{
switch( Sender )
{
case b_Prev:
GoToHistory(-1);
break;
case b_Next:
GoToHistory(1);
break;
case b_Reload:
GoToHistory(0);
break;
}
return true;
}
defaultproperties
{
Begin Object Class=GUIButton Name=PreviousButton
Caption="Prev"
bAutoSize=True
Hint="Go to previous page in history"
WinTop=0.820000
WinLeft=0.050000
WinWidth=0.100000
WinHeight=0.030000
TabOrder=0
OnClick=SRTab_ServerNews.ButtonClicked
OnKeyEvent=PreviousButton.InternalOnKeyEvent
End Object
b_Prev=GUIButton'ServerPerks.SRTab_ServerNews.PreviousButton'
Begin Object Class=GUIButton Name=NextButton
Caption="Next"
bAutoSize=True
Hint="Go to next page in history"
WinTop=0.820000
WinLeft=0.170000
WinWidth=0.100000
WinHeight=0.030000
TabOrder=0
OnClick=SRTab_ServerNews.ButtonClicked
OnKeyEvent=NextButton.InternalOnKeyEvent
End Object
b_Next=GUIButton'ServerPerks.SRTab_ServerNews.NextButton'
Begin Object Class=GUIButton Name=ReloadButton
Caption="Refresh"
bAutoSize=True
Hint="Reload current page"
WinTop=0.820000
WinLeft=0.095000
WinWidth=0.100000
WinHeight=0.030000
TabOrder=0
OnClick=SRTab_ServerNews.ButtonClicked
OnKeyEvent=ReloadButton.InternalOnKeyEvent
End Object
b_Reload=GUIButton'ServerPerks.SRTab_ServerNews.ReloadButton'
Begin Object Class=GUISectionBackground Name=BGSec
bFillClient=True
Caption="Server News"
WinTop=0.018000
WinLeft=0.019240
WinWidth=0.961520
WinHeight=0.798982
OnPreDraw=BGSec.InternalPreDraw
End Object
i_BGSec=GUISectionBackground'ServerPerks.SRTab_ServerNews.BGSec'
Begin Object Class=GUIHTMLTextBox Name=HTMLInfoText
LaunchKFURL=SRTab_ServerNews.SwitchPage
WinTop=0.052000
WinLeft=0.030000
WinWidth=0.945000
WinHeight=0.760000
bBoundToParent=True
bScaleToParent=True
bNeverFocus=True
OnDraw=HTMLInfoText.RenderHTMLText
OnClick=HTMLInfoText.LaunchURL
End Object
HTMLText=GUIHTMLTextBox'ServerPerks.SRTab_ServerNews.HTMLInfoText'
}

View file

@ -0,0 +1,250 @@
// Written by .:..: (2009)
// Base class of all server veterancy types
class SRVeterancyTypes extends KFVeterancyTypes
abstract;
var() localized string CustomLevelInfo;
var() localized array<string> SRLevelEffects; // Added in ver 5.00, dynamic array for level effects.
var() byte NumRequirements;
var() localized string DisableTag,DisableDescription; // Can be set as a reason to hide inventory from specific players.
// Can be used to add in custom stats.
static function AddCustomStats( ClientPerkRepLink Other );
// Return the level of perk that is available, 0 = perk is n/a.
static function byte PerkIsAvailable( ClientPerkRepLink StatOther )
{
local byte i,a,b;
b = StatOther.MaximumLevel+1;
a = Min(StatOther.MinimumLevel,b);
while( true )
{
if( a==b || (a+1)==b )
{
if( a<StatOther.MaximumLevel && LevelIsFinished(StatOther,a) )
++a;
break;
}
i = a+((b-a)>>1);
if( !LevelIsFinished(StatOther,i) ) // Lower!
b = i;
else a = i; // Higher!
}
return Clamp(a,StatOther.MinimumLevel,StatOther.MaximumLevel);
// Check which level it fits in to.
/*for( i=0; i<StatOther.MaximumLevel; i++ )
{
if( !LevelIsFinished(StatOther,i) )
return Clamp(i,StatOther.MinimumLevel,StatOther.MaximumLevel);
}
return StatOther.MaximumLevel;*/
}
// Return the number of different requirements this level has.
static function byte GetRequirementCount( ClientPerkRepLink StatOther, byte CurLevel )
{
if( CurLevel==StatOther.MaximumLevel )
return 0;
return default.NumRequirements;
}
// Return 0-1 % of how much of the progress is done to gain this perk (for menu GUI).
static function float GetTotalProgress( ClientPerkRepLink StatOther, byte CurLevel )
{
local byte i,rc,Minimum;
local int R,V,NegReq;
local float RV;
if( CurLevel==StatOther.MaximumLevel )
return 1.f;
if( StatOther.bMinimalRequirements )
{
Minimum = 0;
CurLevel = Max(CurLevel-StatOther.MinimumLevel,0);
}
else Minimum = StatOther.MinimumLevel;
rc = GetRequirementCount(StatOther,CurLevel);
for( i=0; i<rc; i++ )
{
V = GetPerkProgressInt(StatOther,R,CurLevel,i);
if( StatOther.RequirementScaling!=1 )
R*=StatOther.RequirementScaling;
if( CurLevel>Minimum )
{
GetPerkProgressInt(StatOther,NegReq,(CurLevel-1),i);
if( StatOther.RequirementScaling!=1 )
NegReq*=StatOther.RequirementScaling;
R-=NegReq;
V-=NegReq;
}
if( R<=0 ) // Avoid division by zero error.
RV+=1.f;
else RV+=FClamp(float(V)/(float(R)),0.f,1.f);
}
return RV/float(rc);
}
// Return true if this level is earned.
static function bool LevelIsFinished( ClientPerkRepLink StatOther, byte CurLevel )
{
local byte i,rc;
local int R,V;
if( CurLevel==StatOther.MaximumLevel )
return false;
if( StatOther.bMinimalRequirements )
CurLevel = Max(CurLevel-StatOther.MinimumLevel,0);
rc = GetRequirementCount(StatOther,CurLevel);
for( i=0; i<rc; i++ )
{
V = GetPerkProgressInt(StatOther,R,CurLevel,i);
if( StatOther.RequirementScaling!=1 )
R*=StatOther.RequirementScaling;
if( R>V )
return false;
}
return true;
}
// Return 0-1 % of how much of the progress is done to gain this individual task (for menu GUI).
static function float GetPerkProgress( ClientPerkRepLink StatOther, byte CurLevel, byte ReqNum, out int Numerator, out int Denominator )
{
local byte Minimum;
local int Reduced,Cur,Fin;
if( CurLevel==StatOther.MaximumLevel )
{
Denominator = 1;
Numerator = 1;
return 1.f;
}
if( StatOther.bMinimalRequirements )
{
Minimum = 0;
CurLevel = Max(CurLevel-StatOther.MinimumLevel,0);
}
else Minimum = StatOther.MinimumLevel;
Numerator = GetPerkProgressInt(StatOther,Denominator,CurLevel,ReqNum);
if( StatOther.RequirementScaling!=1 )
Denominator*=StatOther.RequirementScaling;
if( CurLevel>Minimum )
{
GetPerkProgressInt(StatOther,Reduced,CurLevel-1,ReqNum);
if( StatOther.RequirementScaling!=1 )
Reduced*=StatOther.RequirementScaling;
Cur = Max(Numerator-Reduced,0);
Fin = Max(Denominator-Reduced,0);
}
else
{
Cur = Numerator;
Fin = Denominator;
}
if( Fin<=0 ) // Avoid division by zero.
return 1.f;
return FMin(float(Cur)/float(Fin),1.f);
}
// Return int progress for this perk level up.
static function int GetPerkProgressInt( ClientPerkRepLink StatOther, out int FinalInt, byte CurLevel, byte ReqNum )
{
FinalInt = 1;
return 1;
}
static final function int GetDoubleScaling( byte CurLevel, int InValue )
{
CurLevel-=6;
return CurLevel*CurLevel*InValue;
}
// Get display info text for menu GUI
static function string GetVetInfoText( byte Level, byte Type, optional byte RequirementNum )
{
switch( Type )
{
case 0:
return Default.LevelNames[Min(Level,ArrayCount(Default.LevelNames)-1)]; // This was left in the void of unused...
case 1:
if( Level>=Default.SRLevelEffects.Length )
return GetCustomLevelInfo(Level);
return Default.SRLevelEffects[Level];
case 2:
return Default.Requirements[RequirementNum];
default:
return Default.VeterancyName;
}
}
static function string GetCustomLevelInfo( byte Level )
{
return Default.CustomLevelInfo;
}
static final function string GetPercentStr( float InValue )
{
return int(InValue*100.f)$"%";
}
// This function is called for every weapon with and every perk every time trader menu is shown.
// If returned false on any perk, weapon is hidden from the buyable list.
static function bool AllowWeaponInTrader( class<KFWeaponPickup> Pickup, KFPlayerReplicationInfo KFPRI, byte Level )
{
return true;
}
static function byte PreDrawPerk( Canvas C, byte Level, out Material PerkIcon, out Material StarIcon )
{
if ( Level>15 )
{
PerkIcon = Default.OnHUDGoldIcon;
StarIcon = Class'HUDKillingFloor'.Default.VetStarGoldMaterial;
Level-=15;
C.SetDrawColor(64, 64, 255, C.DrawColor.A);
}
else if ( Level>10 )
{
PerkIcon = Default.OnHUDGoldIcon;
StarIcon = Class'HUDKillingFloor'.Default.VetStarGoldMaterial;
Level-=10;
C.SetDrawColor(0, 255, 0, C.DrawColor.A);
}
else if ( Level>5 )
{
PerkIcon = Default.OnHUDGoldIcon;
StarIcon = Class'HUDKillingFloor'.Default.VetStarGoldMaterial;
Level-=5;
C.SetDrawColor(255, 255, 255, C.DrawColor.A);
}
else
{
PerkIcon = Default.OnHUDIcon;
StarIcon = Class'HUDKillingFloor'.Default.VetStarMaterial;
C.SetDrawColor(255, 255, 255, C.DrawColor.A);
}
return Min(Level,15);
}
static final function AddPerkedWeapon( class<KFWeapon> W, KFPlayerReplicationInfo KFPRI, Pawn P )
{
local float C;
local class<KFWeaponPickup> WC;
WC = class<KFWeaponPickup>(W.Default.PickupClass);
if( WC==None )
KFHumanPawn(P).CreateInventory(string(W));
else
{
C = float(WC.Default.cost) * GetCostScaling(KFPRI,WC) * 0.75f;
KFHumanPawn(P).CreateInventoryVeterancy(string(W),C);
}
}
defaultproperties
{
NumRequirements=1
DisableTag="LOCKED"
DisableDescription="Can't buy this weapon because the perk says no."
}

View file

@ -0,0 +1,56 @@
//=============================================================================
// The weight bar from the trader menu, modified by Marco.
//=============================================================================
class SRWeightBar extends KFWeightBar;
function bool MyOnDraw(Canvas C)
{
local int i;
local float TextSizeX, TextSizeY, XScale, BoxScalar;
CurX = WinLeft * C.ClipX;
CurY = (WinTop + WinHeight / 2.5) * C.ClipY;
// Background boxes
C.SetPos(CurX, CurY);
XScale = FMin(BoxSizeX*C.ClipX*MaxBoxes, WinWidth*C.ClipX);
C.DrawTile(BarBack, XScale, BoxSizeY * C.ClipX, 0, 0, BarBack.MaterialUSize()*MaxBoxes, BarBack.MaterialVSize() );
// Encumbrance String
EncString = EncumbranceString$":" @ Eval(NewBoxes!=0,string(CurBoxes)$" (+"$string(NewBoxes)$")",string(CurBoxes)) $ "/" $ MaxBoxes;
C.TextSize(EncString, TextSizeX, TextSizeY);
C.SetPos(CurX, CurY-TextSizeY);
C.DrawColor = CurrentColor;
C.DrawText(EncString);
// Our current weight
C.SetPos(CurX,CurY);
BoxScalar = XScale*FClamp(float(CurBoxes)/float(MaxBoxes),0.f,1.f);
C.DrawTile(BarTop, BoxScalar, BoxSizeY * C.ClipX, 0, 0, BarTop.MaterialUSize()*Min(CurBoxes,MaxBoxes), BarTop.MaterialVSize() );
// Draw weight of selected weapon
if ( NewBoxes != 0 )
{
C.SetPos(CurX+BoxScalar,CurY);
// Selected weapon is not to heavy to carry
if ( CurBoxes + NewBoxes <= MaxBoxes )
{
C.DrawColor = NewColor;
C.DrawTile(BarTop, XScale*(float(NewBoxes)/float(MaxBoxes)), BoxSizeY * C.ClipX, 0, 0, BarTop.MaterialUSize()*NewBoxes, BarTop.MaterialVSize() );
}
// Selected weapon is too heavy
else if( CurBoxes<MaxBoxes )
{
i = MaxBoxes-CurBoxes;
C.DrawColor = WarnColor;
C.DrawTile(BarTop, XScale*(float(i)/float(MaxBoxes)), BoxSizeY * C.ClipX, 0, 0, BarTop.MaterialUSize()*i, BarTop.MaterialVSize() );
}
}
return false;
}
defaultproperties
{
}

View file

@ -0,0 +1,184 @@
// Written by Marco
Class UI_Replication extends ReplicationInfo;
var transient array<UI_Window> ClientWindows;
var transient UI_Window TempNewMenu;
var transient string PendingData;
replication
{
reliable if ( Role==ROLE_Authority )
ClientPendingData,ClientOpenWindow,ClientCloseWindow,ClientAddComponent,ClientSetCompValue,ClientGetValues,ClientSetCompLock;
reliable if( Role<ROLE_Authority )
ServerSendCloseW,ServerSubmitValue;
}
simulated final function DisplayError( string S )
{
Level.GetLocalPlayerController().ClientMessage("ServerPerks_UI warning: "$S);
}
simulated final function UI_Window FindWindow( name ID )
{
local int i;
for( i=(ClientWindows.Length-1); i>=0; --i )
if( ClientWindows[i].WindowID==ID )
return ClientWindows[i];
return None;
}
simulated final function ClientPendingData( string Data )
{
PendingData = PendingData$Data;
}
// WARNING: Use ID with a known name entry on networking.
simulated final function ClientOpenWindow( name ID, float XS, float YS, string Caption )
{
local UI_Window W;
local PlayerController PC;
PC = Level.GetLocalPlayerController();
if( Level.NetMode!=NM_Client && PC!=Owner )
return;
W = FindWindow(ID);
if( W!=None )
{
DisplayError("Tried to open a second window with same ID!");
return;
}
// Big hack in order to easily access newly created menu.
Class'UI_Window'.Default.RepNotify = Self;
PC.Player.GUIController.OpenMenu(string(Class'UI_Window'),Caption);
Class'UI_Window'.Default.RepNotify = None;
W = TempNewMenu;
TempNewMenu = None;
if( W==None )
{
DisplayError("Window couldn't be created!");
return;
}
ClientWindows[ClientWindows.Length] = W;
W.RepNotify = Self;
W.WindowID = ID;
W.WinTop = (1.f-YS) * 0.5f;
W.WinLeft = (1.f-XS) * 0.5f;
W.WinWidth = XS;
W.WinHeight = YS;
W.DefaultLeft = W.WinLeft;
W.DefaultTop = W.WinTop;
W.DefaultWidth = W.WinWidth;
W.DefaultHeight = W.WinHeight;
}
simulated final function ClientCloseWindow( name ID )
{
local int i;
for( i=(ClientWindows.Length-1); i>=0; --i )
{
if( ClientWindows[i].WindowID==ID )
{
ClientWindows[i].RepNotify = None;
GUIController(Level.GetLocalPlayerController().Player.GUIController).RemoveMenu(ClientWindows[i],true);
ClientWindows.Remove(i,1);
break;
}
}
}
/* Component ID:
0 - Normal button, will callback ServerSubmitValue when pressed.
1 - Submit button, will send all changed values when pressed.
2 - Close button, will close menu.
3 - String editbox.
4 - Float editbox, MinValue:MaxValue:StepValue:CurrentValue
5 - Int editbox, same as above.
6 - Combo box, CurrentItemIndex;Item Value1:Item Value2:Item Value3:etc
7 - Checkbox, 0 = false, 1 = true
8 - Textbox, Value = text to draw.
*/
simulated final function ClientAddComponent( name ID, int CompID, byte Type, bool bInstant, bool bLock, float X, float Y, float XS, float YS, string Value, optional string ToolTip )
{
local UI_Window W;
W = FindWindow(ID);
if( W!=None )
W.AddCompID(CompID,Type,bInstant,bLock,X,Y,XS,YS,PendingData$Value,ToolTip);
PendingData = "";
}
simulated final function ClientSetCompValue( name ID, int CompID, string Value )
{
local UI_Window W;
W = FindWindow(ID);
if( W!=None )
W.SetComponentData(CompID,PendingData$Value);
PendingData = "";
}
simulated final function ClientSetCompLock( name ID, int CompID, bool bLocked )
{
local UI_Window W;
W = FindWindow(ID);
if( W!=None )
W.SetComponentLock(CompID,bLocked);
}
simulated final function ClientGetValues( name ID )
{
local UI_Window W;
W = FindWindow(ID);
if( W!=None )
W.SendChanges();
}
simulated final function WindowClosed( UI_Window W )
{
local int i;
for( i=(ClientWindows.Length-1); i>=0; --i )
if( ClientWindows[i]==W )
{
ClientWindows.Remove(i,1);
break;
}
ServerSendCloseW(W.WindowID);
W.RepNotify = None;
}
simulated function Destroyed()
{
local int i;
local PlayerController PC;
if( Level.NetMode!=NM_DedicatedServer )
{
PC = Level.GetLocalPlayerController();
// Close all windows to prevent memory access errors.
for( i=(ClientWindows.Length-1); i>=0; --i )
{
ClientWindows[i].RepNotify = None;
GUIController(PC.Player.GUIController).RemoveMenu(ClientWindows[i],true);
}
ClientWindows.Length = 0;
}
}
final function ServerSendCloseW( name ID )
{
DlgWindowClosed(ID);
}
final function ServerSubmitValue( name ID, int CompID, string Value )
{
DlgSubmittedValue(ID,CompID,Value);
}
delegate DlgWindowClosed( name ID );
delegate DlgSubmittedValue( name ID, int CompID, string Value );
defaultproperties
{
bOnlyRelevantToOwner=True
bAlwaysRelevant=False
}

View file

@ -0,0 +1,296 @@
Class UI_Window extends FloatingWindow;
struct FComponentData
{
var GUIComponent Component;
var string OldData;
var byte Type;
var bool bInstantUpdate,bLocked;
};
var name WindowID;
var array<FComponentData> MyComponents;
var UI_Replication RepNotify;
var bool bSecureChanges;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController,MyOwner);
if( Default.RepNotify!=None )
{
Default.RepNotify.TempNewMenu = Self;
Default.RepNotify = None;
}
}
function HandleParameters(string Param1, string Param2)
{
t_WindowTitle.SetCaption(Param1);
WindowName = Param1;
}
function Closed( GUIComponent Sender, bool bCancelled )
{
if( RepNotify!=None )
RepNotify.WindowClosed(Self);
RepNotify = None;
Super.Closed(Sender, bCancelled);
}
final function InitFloatValue( moFloatEdit C, string V )
{
local string S;
local float FA,FB,FC;
Divide(V,":",S,V);
FA = float(S);
Divide(V,":",S,V);
FB = float(S);
Divide(V,":",S,V);
FC = float(S);
C.Setup(FA,FB,FC);
C.SetComponentValue(V,true);
}
final function InitIntValue( moNumericEdit C, string V )
{
local string S;
local int FA,FB,FC;
Divide(V,":",S,V);
FA = int(S);
Divide(V,":",S,V);
FB = int(S);
Divide(V,":",S,V);
FC = int(S);
C.Setup(FA,FB,FC);
C.SetComponentValue(V,true);
}
final function InitComboBox( moComboBox C, string V )
{
local string S;
local array<string> AR;
local int i;
Divide(V,";",S,V);
Split(V,":",AR);
if( C.ItemCount()>0 )
C.ResetComponent();
for( i=0; i<AR.Length; ++i )
C.AddItem(AR[i]);
C.SilentSetIndex(int(S));
}
final function bool AddCompID( int ID, byte Type, bool bInstant, bool bLock, float X, float Y, float XS, float YS, string Value, string ToolTipS )
{
local GUIComponent NC;
bSecureChanges = true;
if( MyComponents.Length<=ID )
MyComponents.Length = (ID+1);
NC = MyComponents[ID].Component;
MyComponents[ID].OldData = "";
if( NC!=None && MyComponents[ID].Type!=Type )
{
RemoveComponent(NC);
NC = None;
}
switch( Type )
{
case 0: // Button.
case 1: // Submit.
case 2: // Close.
if( NC==None )
NC = AddComponent(string(Class'GUIButton'));
GUIButton(NC).Caption = Value;
GUIButton(NC).OnClick = InternalOnClick;
break;
case 3: // Editbox
if( NC==None )
NC = AddComponent(string(Class'moEditBox'));
moEditBox(NC).SetComponentValue(Value,true);
moEditBox(NC).OnChange = ValueChange;
MyComponents[ID].OldData = Value;
break;
case 4: // Floating point editbox
if( NC==None )
NC = AddComponent(string(Class'moFloatEdit'));
InitFloatValue(moFloatEdit(NC),Value);
moFloatEdit(NC).OnChange = ValueChange;
break;
case 5: // Numeric editbox
if( NC==None )
NC = AddComponent(string(Class'moNumericEdit'));
InitIntValue(moNumericEdit(NC),Value);
moNumericEdit(NC).OnChange = ValueChange;
break;
case 6: // Combo box.
if( NC==None )
NC = AddComponent(string(Class'moComboBox'));
InitComboBox(moComboBox(NC),Value);
moComboBox(NC).OnChange = ValueChange;
break;
case 7: // Checkbox
if( NC==None )
NC = AddComponent(string(Class'moCheckBox'));
moCheckBox(NC).SetComponentValue(Value,true);
moCheckBox(NC).OnChange = ValueChange;
break;
case 8: // Textbox.
if( NC==None )
NC = AddComponent(string(Class'GUIScrollTextBox'));
GUIScrollTextBox(NC).SetContent(Value);
break;
default:
Warn("Unknown component ID.");
bSecureChanges = false;
return false;
}
MyComponents[ID].bLocked = bLock;
MyComponents[ID].bInstantUpdate = bInstant;
MyComponents[ID].Component = NC;
MyComponents[ID].Type = Type;
NC.WinTop = Y;
NC.WinLeft = X;
NC.WinWidth = XS;
NC.WinHeight = YS;
if( bLock )
NC.DisableMe();
else NC.EnableMe();
if( ToolTipS!="" )
{
if( NC.ToolTip!=None )
NC.SetToolTipText(ToolTipS);
if( GUIMenuOption(NC)!=None )
GUIMenuOption(NC).SetCaption(ToolTipS);
}
bSecureChanges = false;
return true;
}
final function string GetComponentData( int Index )
{
if( MyComponents.Length<=Index || MyComponents[Index].Component==None )
return "";
switch( MyComponents[Index].Type )
{
case 0: // Button.
case 1: // Submit.
case 2: // Close.
case 8: // Textbox
return "";
case 6:
return string(moComboBox(MyComponents[Index].Component).GetIndex());
case 7:
return Eval(moCheckBox(MyComponents[Index].Component).IsChecked(),"1","0");
default:
return GUIMenuOption(MyComponents[Index].Component).GetComponentValue();
}
}
final function bool SetComponentData( int Index, string Data )
{
if( MyComponents.Length<=Index || MyComponents[Index].Component==None )
return false;
bSecureChanges = true;
switch( MyComponents[Index].Type )
{
case 0: // Button.
case 1:
case 2:
GUIButton(MyComponents[Index].Component).Caption = Data;
break;
case 6:
moComboBox(MyComponents[Index].Component).SilentSetIndex(int(Data));
break;
case 8:
GUIScrollTextBox(MyComponents[Index].Component).SetContent(Data);
break;
default:
MyComponents[Index].OldData = Data;
GUIMenuOption(MyComponents[Index].Component).SetComponentValue(Data,true);
}
bSecureChanges = false;
return true;
}
final function bool SetComponentLock( int Index, bool bLocked )
{
if( MyComponents.Length<=Index || MyComponents[Index].Component==None || MyComponents[Index].bLocked==bLocked )
return false;
bSecureChanges = true;
MyComponents[Index].bLocked = bLocked;
if( bLocked )
MyComponents[Index].Component.DisableMe();
else MyComponents[Index].Component.EnableMe();
bSecureChanges = false;
return true;
}
final function SendChanges()
{
local string S;
local int i;
for( i=0; i<MyComponents.Length; ++i )
if( MyComponents[i].Component!=None && MyComponents[i].Type>=3 )
{
S = GetComponentData(i);
if( S!=MyComponents[i].OldData )
{
RepNotify.ServerSubmitValue(WindowID,i,S);
MyComponents[i].OldData = S;
}
}
}
function bool InternalOnClick(GUIComponent Sender)
{
local int i;
local string S;
if( !bSecureChanges )
{
for( i=0; i<MyComponents.Length; ++i )
if( MyComponents[i].Component==Sender )
{
if( MyComponents[i].Type==1 && !MyComponents[i].bLocked )
{
SendChanges();
RepNotify.ServerSubmitValue(WindowID,i,"");
}
else if( MyComponents[i].Type==2 && !MyComponents[i].bLocked )
{
Controller.RemoveMenu(Self);
}
else if( MyComponents[i].bInstantUpdate && !MyComponents[i].bLocked )
{
S = GetComponentData(i);
if( MyComponents[i].Type==0 || S!=MyComponents[i].OldData )
{
RepNotify.ServerSubmitValue(WindowID,i,S);
MyComponents[i].OldData = S;
}
}
Return True;
}
}
Return False;
}
function ValueChange(GUIComponent Sender)
{
InternalOnClick(Sender);
}
defaultproperties
{
Begin Object Class=FloatingImage Name=FloatingFrameBg
Image=Texture'KF_InterfaceArt_tex.Menu.Thin_border'
DropShadow=None
ImageStyle=ISTY_Stretched
ImageRenderStyle=MSTY_Normal
WinTop=0.040000
WinLeft=0.000000
WinWidth=1.000000
WinHeight=0.960000
RenderWeight=0.000003
End Object
i_FrameBG=FloatingImage'ServerPerks.UI_Window.FloatingFrameBg'
bAllowedAsLast=True
}

View file

@ -0,0 +1,57 @@
<html>
<head><title>Index of /kf_sources/ServerPerks/Classes/</title></head>
<body>
<h1>Index of /kf_sources/ServerPerks/Classes/</h1><hr><pre><a href="../">../</a>
<a href="ClientPerkRepLink.uc">ClientPerkRepLink.uc</a> 06-Oct-2019 10:31 15364
<a href="DualWeaponsManager.uc">DualWeaponsManager.uc</a> 06-Oct-2019 10:31 1697
<a href="GUIHTMLTextBox.uc">GUIHTMLTextBox.uc</a> 06-Oct-2019 10:31 22731
<a href="KFPCServ.uc">KFPCServ.uc</a> 06-Oct-2019 10:31 14496
<a href="KFVetEarnedMessagePL.uc">KFVetEarnedMessagePL.uc</a> 06-Oct-2019 10:31 801
<a href="KFVetEarnedMessageSR.uc">KFVetEarnedMessageSR.uc</a> 06-Oct-2019 10:31 2812
<a href="SRBufferedTCPLink.uc">SRBufferedTCPLink.uc</a> 06-Oct-2019 10:31 2606
<a href="SRBuyMenuFilter.uc">SRBuyMenuFilter.uc</a> 06-Oct-2019 10:31 6747
<a href="SRBuyMenuSaleList.uc">SRBuyMenuSaleList.uc</a> 06-Oct-2019 10:31 16419
<a href="SRBuyMenuSaleListBox.uc">SRBuyMenuSaleListBox.uc</a> 06-Oct-2019 10:31 500
<a href="SRClientSettings.uc">SRClientSettings.uc</a> 06-Oct-2019 10:31 1111
<a href="SRCustomProgress.uc">SRCustomProgress.uc</a> 06-Oct-2019 10:31 1342
<a href="SRCustomProgressFloat.uc">SRCustomProgressFloat.uc</a> 06-Oct-2019 10:31 520
<a href="SRCustomProgressInt.uc">SRCustomProgressInt.uc</a> 06-Oct-2019 10:31 514
<a href="SRGUIBuyMenu.uc">SRGUIBuyMenu.uc</a> 06-Oct-2019 10:31 1540
<a href="SRGUIBuyWeaponInfoPanel.uc">SRGUIBuyWeaponInfoPanel.uc</a> 06-Oct-2019 10:31 2369
<a href="SRHUDKillingFloor.uc">SRHUDKillingFloor.uc</a> 06-Oct-2019 10:31 50546
<a href="SRHumanPawn.uc">SRHumanPawn.uc</a> 06-Oct-2019 10:31 15962
<a href="SRInvasionLoginMenu.uc">SRInvasionLoginMenu.uc</a> 06-Oct-2019 10:31 16037
<a href="SRKFBuyMenuInvList.uc">SRKFBuyMenuInvList.uc</a> 06-Oct-2019 10:31 18892
<a href="SRKFBuyMenuInvListBox.uc">SRKFBuyMenuInvListBox.uc</a> 06-Oct-2019 10:31 615
<a href="SRKFQuickPerkSelect.uc">SRKFQuickPerkSelect.uc</a> 06-Oct-2019 10:31 3562
<a href="SRKFTab_BuyMenu.uc">SRKFTab_BuyMenu.uc</a> 06-Oct-2019 10:31 7894
<a href="SRKFTab_Perks.uc">SRKFTab_Perks.uc</a> 06-Oct-2019 10:31 2565
<a href="SRLevelCleanup.uc">SRLevelCleanup.uc</a> 06-Oct-2019 10:31 1453
<a href="SRLobbyChat.uc">SRLobbyChat.uc</a> 06-Oct-2019 10:31 603
<a href="SRLobbyFooter.uc">SRLobbyFooter.uc</a> 06-Oct-2019 10:31 1837
<a href="SRLobbyMenu.uc">SRLobbyMenu.uc</a> 06-Oct-2019 10:31 13455
<a href="SRMenuAddition.uc">SRMenuAddition.uc</a> 06-Oct-2019 10:31 1771
<a href="SRModelSelect.uc">SRModelSelect.uc</a> 06-Oct-2019 10:31 4314
<a href="SRPerkProgressList.uc">SRPerkProgressList.uc</a> 06-Oct-2019 10:31 1308
<a href="SRPerkProgressListBox.uc">SRPerkProgressListBox.uc</a> 06-Oct-2019 10:31 270
<a href="SRPerkSelectList.uc">SRPerkSelectList.uc</a> 06-Oct-2019 10:31 4678
<a href="SRPerkSelectListBox.uc">SRPerkSelectListBox.uc</a> 06-Oct-2019 10:31 264
<a href="SRProfilePage.uc">SRProfilePage.uc</a> 06-Oct-2019 10:31 316
<a href="SRScoreBoard.uc">SRScoreBoard.uc</a> 06-Oct-2019 10:31 14947
<a href="SRStatList.uc">SRStatList.uc</a> 06-Oct-2019 10:31 5282
<a href="SRStatListBox.uc">SRStatListBox.uc</a> 06-Oct-2019 10:31 527
<a href="SRStatsBase.uc">SRStatsBase.uc</a> 06-Oct-2019 10:31 654
<a href="SRSteamStatsGet.uc">SRSteamStatsGet.uc</a> 06-Oct-2019 10:31 1504
<a href="SRTab_Base.uc">SRTab_Base.uc</a> 06-Oct-2019 10:31 204
<a href="SRTab_MidGameHelp.uc">SRTab_MidGameHelp.uc</a> 06-Oct-2019 10:31 6611
<a href="SRTab_MidGamePerks.uc">SRTab_MidGamePerks.uc</a> 06-Oct-2019 10:31 5376
<a href="SRTab_MidGameStats.uc">SRTab_MidGameStats.uc</a> 06-Oct-2019 10:31 1107
<a href="SRTab_MidGameVoiceChat.uc">SRTab_MidGameVoiceChat.uc</a> 06-Oct-2019 10:31 15816
<a href="SRTab_Profile.uc">SRTab_Profile.uc</a> 06-Oct-2019 10:31 4770
<a href="SRTab_ServerNews.uc">SRTab_ServerNews.uc</a> 06-Oct-2019 10:31 5357
<a href="SRVeterancyTypes.uc">SRVeterancyTypes.uc</a> 06-Oct-2019 10:31 7099
<a href="SRWeightBar.uc">SRWeightBar.uc</a> 06-Oct-2019 10:31 1921
<a href="UI_Replication.uc">UI_Replication.uc</a> 06-Oct-2019 10:31 4788
<a href="UI_Window.uc">UI_Window.uc</a> 06-Oct-2019 10:31 7473
</pre><hr></body>
</html>

View file

@ -0,0 +1,7 @@
<html>
<head><title>Index of /kf_sources/ServerPerks/</title></head>
<body>
<h1>Index of /kf_sources/ServerPerks/</h1><hr><pre><a href="../">../</a>
<a href="Classes/">Classes/</a> 29-Jun-2025 19:43 -
</pre><hr></body>
</html>