Added base ServerExt and ServerExtMut

This commit is contained in:
Forrest Keller 2017-10-19 21:00:49 -05:00
parent 08fbb7c91c
commit 439d1b2ab2
208 changed files with 100716 additions and 0 deletions

View File

@ -0,0 +1,231 @@
class ExtAutoPurchaseHelper extends KFAutoPurchaseHelper within ExtPlayerController;
final function class<KFPerk> GetBasePerk()
{
return (ActivePerkManager!=None && ActivePerkManager.CurrentPerk!=None) ? ActivePerkManager.CurrentPerk.BasePerk : None;
}
final function Ext_PerkBase GetExtPerk()
{
return ActivePerkManager!=None ? ActivePerkManager.CurrentPerk : None;
}
function DoAutoPurchase()
{
local int PotentialDosh, i;
local Array <STraderItem> OnPerkWeapons;
local STraderItem TopTierWeapon;
local int ItemIndex;
local bool bSecondaryWeaponPurchased;
local bool bUpgradeSuccess;
local bool bAutoFillPurchasedItem;
local string AutoFillMessageString;
local Ext_PerkBase EP;
GetTraderItems();
EP = GetExtPerk();
if( EP==None || EP.AutoBuyLoadOutPath.length == 0)
return;
for( i = 0; i<EP.AutoBuyLoadOutPath.length; i++ )
{
ItemIndex = TraderItems.SaleItems.Find('WeaponDef', EP.AutoBuyLoadOutPath[i]);
if(ItemIndex != INDEX_NONE)
OnPerkWeapons.AddItem(TraderItems.SaleItems[ItemIndex]);
}
SellOffPerkWeapons();
TopTierWeapon = GetTopTierWeapon(OnPerkWeapons);
//can I afford my top teir without selling my current weapon?
if(!DoIOwnThisWeapon(TopTierWeapon) && GetCanAfford( GetAdjustedBuyPriceFor(TopTierWeapon) + DoshBuffer ) && CanCarry( TopTierWeapon ) )
{
bUpgradeSuccess = AttemptUpgrade(TotalDosh, OnPerkWeapons, true);
}
else
{
PotentialDosh = GetPotentialDosh();
bUpgradeSuccess = AttemptUpgrade(PotentialDosh+TotalDosh, OnPerkWeapons);
}
bAutoFillPurchasedItem = StartAutoFill();
if(DoIOwnThisWeapon(TopTierWeapon))
{
while(AttemptToPurchaseNextLowerTier(TotalDosh, OnPerkWeapons))
{
bSecondaryWeaponPurchased = true;
AttemptToPurchaseNextLowerTier(TotalDosh, OnPerkWeapons);
}
}
MyKFIM.ServerCloseTraderMenu();
if(bUpgradeSuccess)
{
AutoFillMessageString = class'KFCommon_LocalizedStrings'.default.WeaponUpgradeComepleteString;
}
else if(bSecondaryWeaponPurchased)
{
AutoFillMessageString = class'KFCommon_LocalizedStrings'.default.SecondaryWeaponPurchasedString;
}
else if(bAutoFillPurchasedItem)
{
AutoFillMessageString = class'KFCommon_LocalizedStrings'.default.AutoFillCompleteString;
}
else
{
AutoFillMessageString = class'KFCommon_LocalizedStrings'.default.NoItemsPurchasedString;
}
if(MyGFxHUD != none)
{
MyGFxHUD.ShowNonCriticalMessage( class'KFCommon_LocalizedStrings'.default.AutoTradeCompleteString$AutoFillMessageString );
}
}
function SellOnPerkWeapons()
{
local int i;
local class<KFPerk> Perk;
Perk = GetBasePerk();
if( Perk!=None )
{
for (i = 0; i < OwnedItemList.length; i++)
{
if( OwnedItemList[i].DefaultItem.AssociatedPerkClasses.Find(Perk)!=INDEX_NONE && OwnedItemList[i].DefaultItem.BlocksRequired != -1)
{
SellWeapon(OwnedItemList[i], i);
i=-1;
}
}
}
}
function SellOffPerkWeapons()
{
local int i;
local Ext_PerkBase EP;
EP = GetExtPerk();
for (i = 0; i < OwnedItemList.length; i++)
{
if( OwnedItemList[i].DefaultItem.AssociatedPerkClasses.Find(EP.BasePerk)==INDEX_NONE && OwnedItemList[i].DefaultItem.BlocksRequired != -1 && OwnedItemList[i].SellPrice != 0 )
{
if(EP.AutoBuyLoadOutPath.Find(OwnedItemList[i].DefaultItem.WeaponDef) == INDEX_NONE)
{
SellWeapon(OwnedItemList[i], i);
i=-1;
}
}
}
}
function InitializeOwnedItemList()
{
local Inventory Inv;
local KFWeapon KFW;
local KFPawn_Human KFP;
local Ext_PerkBase EP;
EP = GetExtPerk();
OwnedItemList.length = 0;
TraderItems = KFGameReplicationInfo( WorldInfo.GRI ).TraderItems;
KFP = KFPawn_Human( Pawn );
if( KFP != none )
{
// init armor purchase values
ArmorItem.SpareAmmoCount = KFP.Armor;
ArmorItem.MaxSpareAmmo = KFP.GetMaxArmor();
ArmorItem.AmmoPricePerMagazine = TraderItems.ArmorPrice * ActivePerkManager.GetArmorDiscountMod();
ArmorItem.DefaultItem.WeaponDef = TraderItems.ArmorDef;
// init grenade purchase values
GrenadeItem.SpareAmmoCount = MyKFIM.GrenadeCount;
GrenadeItem.MaxSpareAmmo = ActivePerkManager.MaxGrenadeCount;
GrenadeItem.AmmoPricePerMagazine = TraderItems.GrenadePrice;
GrenadeItem.DefaultItem.WeaponDef = EP.GrenadeWeaponDef;
// @temp: fill in stuff that is normally serialized in the archetype
GrenadeItem.DefaultItem.AssociatedPerkClasses[0] = CurrentPerk.Class;
for ( Inv = MyKFIM.InventoryChain; Inv != none; Inv = Inv.Inventory )
{
KFW = KFWeapon( Inv );
if( KFW != none )
{
// Set the weapon information and add it to the OwnedItemList
SetWeaponInformation( KFW );
}
}
if(MyGfxManager != none && MyGfxManager.TraderMenu != none)
{
MyGfxManager.TraderMenu.OwnedItemList = OwnedItemList;
}
}
}
function int AddItemByPriority( out SItemInformation WeaponInfo )
{
local byte i;
local byte WeaponGroup, WeaponPriority;
local byte BestIndex;
local class<KFPerk> Perk;
Perk = GetBasePerk();
BestIndex = 0;
WeaponGroup = WeaponInfo.DefaultItem.InventoryGroup;
WeaponPriority = WeaponInfo.DefaultItem.GroupPriority;
for( i = 0; i < OwnedItemList.length; i++ )
{
// If the weapon belongs in the group prior to the current weapon, we've found the spot
if( WeaponGroup < OwnedItemList[i].DefaultItem.InventoryGroup )
{
BestIndex = i;
break;
}
else if( WeaponGroup == OwnedItemList[i].DefaultItem.InventoryGroup )
{
if( WeaponPriority > OwnedItemList[i].DefaultItem.GroupPriority )
{
// if the weapon is in the same group but has a higher priority, we've found the spot
BestIndex = i;
break;
}
else if( WeaponPriority == OwnedItemList[i].DefaultItem.GroupPriority && WeaponInfo.DefaultItem.AssociatedPerkClasses.Find(Perk)>=0 )
{
// if the weapons have the same priority give the slot to the on perk weapon
BestIndex = i;
break;
}
}
else
{
// Covers the case if this weapon is the only item in the last group
BestIndex = i + 1;
}
}
OwnedItemList.InsertItem( BestIndex, WeaponInfo );
// Add secondary ammo immediately after the main weapon
if( WeaponInfo.DefaultItem.WeaponDef.static.UsesSecondaryAmmo() )
{
WeaponInfo.bIsSecondaryAmmo = true;
WeaponInfo.SellPrice = 0;
OwnedItemList.InsertItem( BestIndex + 1, WeaponInfo );
}
if( MyGfxManager != none && MyGfxManager.TraderMenu != none )
{
MyGfxManager.TraderMenu.OwnedItemList = OwnedItemList;
}
return BestIndex;
}

View File

@ -0,0 +1,48 @@
Class ExtCharDataInfo extends Object
config(Game)
perobjectconfig
DependsOn(ExtPlayerReplicationInfo);
var config byte HeadMeshIndex,HeadSkinIndex,BodyMeshIndex,BodySkinIndex,AttachmentMesh0,AttachmentSkin0,AttachmentMesh1,AttachmentSkin1,AttachmentMesh2,AttachmentSkin2,HasInit;
final function FMyCustomChar LoadData()
{
local FMyCustomChar R;
if( HasInit==0 )
{
AttachmentMesh0 = 255;
AttachmentMesh1 = 255;
AttachmentMesh2 = 255;
}
R.HeadMeshIndex = HeadMeshIndex;
R.HeadSkinIndex = HeadSkinIndex;
R.BodyMeshIndex = BodyMeshIndex;
R.BodySkinIndex = BodySkinIndex;
R.AttachmentMeshIndices[0] = AttachmentMesh0;
R.AttachmentSkinIndices[0] = AttachmentSkin0;
R.AttachmentMeshIndices[1] = AttachmentMesh1;
R.AttachmentSkinIndices[1] = AttachmentSkin1;
R.AttachmentMeshIndices[2] = AttachmentMesh2;
R.AttachmentSkinIndices[2] = AttachmentSkin2;
return R;
}
final function SaveData( FMyCustomChar R )
{
HeadMeshIndex = R.HeadMeshIndex;
HeadSkinIndex = R.HeadSkinIndex;
BodyMeshIndex = R.BodyMeshIndex;
BodySkinIndex = R.BodySkinIndex;
AttachmentMesh0 = R.AttachmentMeshIndices[0];
AttachmentSkin0 = R.AttachmentSkinIndices[0];
AttachmentMesh1 = R.AttachmentMeshIndices[1];
AttachmentSkin1 = R.AttachmentSkinIndices[1];
AttachmentMesh2 = R.AttachmentMeshIndices[2];
AttachmentSkin2 = R.AttachmentSkinIndices[2];
HasInit = 1;
SaveConfig();
}
defaultproperties
{
}

View File

@ -0,0 +1,467 @@
// Only a helper class to hold code.
class ExtCharacterInfo extends Object
abstract;
// Hack fix for not being able to compile materials in run-time.
static final function CloneMIC( MaterialInstanceConstant B )
{
local int i;
local MaterialInstanceConstant M;
local LinearColor C;
M = MaterialInstanceConstant(B.Parent);
if( M==None )
return;
B.SetParent(M.Parent);
for( i=0; i<M.TextureParameterValues.Length; ++i )
if( M.TextureParameterValues[i].ParameterValue!=None )
B.SetTextureParameterValue(M.TextureParameterValues[i].ParameterName,M.TextureParameterValues[i].ParameterValue);
for( i=0; i<M.ScalarParameterValues.Length; ++i )
B.SetScalarParameterValue(M.ScalarParameterValues[i].ParameterName,M.ScalarParameterValues[i].ParameterValue);
for( i=0; i<M.VectorParameterValues.Length; ++i )
{
C = M.VectorParameterValues[i].ParameterValue;
B.SetVectorParameterValue(M.VectorParameterValues[i].ParameterName,C);
}
}
static final function Object SafeLoadObject( string S, Class ObjClass )
{
local Object O;
O = FindObject(S,ObjClass);
return O!=None ? O : DynamicLoadObject(S,ObjClass);
}
/** Sets the pawns character mesh from it's CharacterInfo, and updates instance of player in map if there is one. */
static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI )
{
local ExtPlayerReplicationInfo EPRI;
local int AttachmentIdx, CosmeticMeshIdx;
local bool bMaskHeadMesh, bCustom;
EPRI = ExtPlayerReplicationInfo(KFPRI);
if ( KFPRI == none )
{
`Warn("Does not have a KFPRI" @ C);
return;
}
bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false);
// Body mesh & skin. Index of 255 implies use index 0 (default).
SetBodyMeshAndSkin(C,
bCustom ? EPRI.CustomCharacter.BodyMeshIndex : KFPRI.RepCustomizationInfo.BodyMeshIndex,
bCustom ? EPRI.CustomCharacter.BodySkinIndex : KFPRI.RepCustomizationInfo.BodySkinIndex,
KFP);
// Head mesh & skin. Index of 255 implies use index 0 (default).
SetHeadMeshAndSkin(C,
bCustom ? EPRI.CustomCharacter.HeadMeshIndex : KFPRI.RepCustomizationInfo.HeadMeshIndex,
bCustom ? EPRI.CustomCharacter.HeadSkinIndex : KFPRI.RepCustomizationInfo.HeadSkinIndex,
KFP);
// skip dedicated for purely cosmetic stuff
if ( KFP.WorldInfo.NetMode != NM_DedicatedServer )
{
// Must clear all attachments before trying to attach new ones,
// otherwise we might accidentally remove things we're not supposed to
for( AttachmentIdx=0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ )
{
// Clear any previous attachments from other characters
C.DetachAttachment(AttachmentIdx, KFP);
}
// Cosmetic attachment mesh & skin. Index of 255 implies don't use any attachments (default)
for( AttachmentIdx=0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ )
{
CosmeticMeshIdx = bCustom ? EPRI.CustomCharacter.AttachmentMeshIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx];
if ( CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX )
{
bMaskHeadMesh = bMaskHeadMesh || C.CosmeticVariants[CosmeticMeshIdx].bMaskHeadMesh;
// Attach all saved attachments to the character
SetAttachmentMeshAndSkin(C,
CosmeticMeshIdx,
bCustom ? EPRI.CustomCharacter.AttachmentSkinIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentSkinIndices[AttachmentIdx],
KFP, KFPRI);
}
}
// initial mask for new MIC (also see ResetHeadMaskParam())
if ( bMaskHeadMesh && KFP.CharacterMICs[1] != None )
KFP.CharacterMICs[1].SetScalarParameterValue('Scalar_Mask', 1.f);
}
}
static final function SetBodyMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentBodyMeshIndex,
byte CurrentBodySkinIndex,
KFPawn KFP )
{
local SkeletalMesh CharBodyMesh;
// Character Mesh
if( C.BodyVariants.length > 0 )
{
// Assign a skin to the body mesh as a material override
CurrentBodyMeshIndex = (CurrentBodyMeshIndex < C.BodyVariants.length) ? CurrentBodyMeshIndex : 0;
// Load the meshes
CharBodyMesh = SkeletalMesh(SafeLoadObject(C.BodyVariants[CurrentBodyMeshIndex].MeshName, class'SkeletalMesh'));
// Assign the body mesh to the pawn
KFP.Mesh.SetSkeletalMesh(CharBodyMesh);
if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
{
SetBodySkinMaterial(C, C.BodyVariants[CurrentBodyMeshIndex], CurrentBodySkinIndex, KFP);
}
}
else
{
`warn("Character does not have a valid mesh");
}
}
static final function SetBodySkinMaterial( KFCharacterInfo_Human C, OutfitVariants CurrentVariant, byte NewSkinIndex, KFPawn KFP)
{
local int i;
if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
{
if( CurrentVariant.SkinVariations.length > 0 )
{
// Assign a skin to the body mesh as a material override
NewSkinIndex = (NewSkinIndex < CurrentVariant.SkinVariations.length) ? NewSkinIndex : 0;
KFP.Mesh.SetMaterial(C.BodyMaterialID, CurrentVariant.SkinVariations[NewSkinIndex].Skin);
}
else
{
// Use material specified in the mesh asset
for( i=0; i<KFP.Mesh.GetNumElements(); i++ )
{
KFP.Mesh.SetMaterial(i, none);
}
}
// Initialize MICs
if( KFP.Mesh != None )
{
KFP.CharacterMICs[0] = KFP.Mesh.CreateAndSetMaterialInstanceConstant(C.BodyMaterialID);
CloneMIC(KFP.CharacterMICs[0]);
}
}
}
static final function SetHeadSkinMaterial( KFCharacterInfo_Human C, OutfitVariants CurrentVariant, byte NewSkinIndex, KFPawn KFP)
{
local int i;
if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
{
if( CurrentVariant.SkinVariations.length > 0 )
{
// Assign a skin to the body mesh as a material override
NewSkinIndex = (NewSkinIndex < CurrentVariant.SkinVariations.length) ? NewSkinIndex : 0;
KFP.ThirdPersonHeadMeshComponent.SetMaterial(C.HeadMaterialID, CurrentVariant.SkinVariations[NewSkinIndex].Skin);
}
else
{
// Use material specified in the mesh asset
for( i=0; i<KFP.ThirdPersonHeadMeshComponent.GetNumElements(); i++ )
{
KFP.ThirdPersonHeadMeshComponent.SetMaterial(i, none);
}
}
// Initialize MICs
if( KFP.ThirdPersonHeadMeshComponent != None )
{
KFP.CharacterMICs[1] = KFP.ThirdPersonHeadMeshComponent.CreateAndSetMaterialInstanceConstant(C.HeadMaterialID);
CloneMIC(KFP.CharacterMICs[1]);
}
}
}
static final function SetHeadMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentHeadMeshIndex,
byte CurrentHeadSkinIndex,
KFPawn KFP )
{
local SkeletalMesh CharHeadMesh;
if ( C.HeadVariants.length > 0 )
{
CurrentHeadMeshIndex = (CurrentHeadMeshIndex < C.HeadVariants.length) ? CurrentHeadMeshIndex : 0;
CharHeadMesh = SkeletalMesh(SafeLoadObject(C.HeadVariants[CurrentHeadMeshIndex].MeshName, class'SkeletalMesh'));
// Parent the third person head mesh to the body mesh
KFP.ThirdPersonHeadMeshComponent.SetSkeletalMesh(CharHeadMesh);
KFP.ThirdPersonHeadMeshComponent.SetScale(C.DefaultMeshScale);
KFP.ThirdPersonHeadMeshComponent.SetParentAnimComponent(KFP.Mesh);
KFP.ThirdPersonHeadMeshComponent.SetShadowParent(KFP.Mesh);
KFP.ThirdPersonHeadMeshComponent.SetLODParent(KFP.Mesh);
KFP.AttachComponent(KFP.ThirdPersonHeadMeshComponent);
if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
{
SetHeadSkinMaterial(C, C.HeadVariants[CurrentHeadMeshIndex], CurrentHeadSkinIndex, KFP);
}
}
}
static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
int PawnAttachmentIndex,
const out AttachmentVariants CurrentVariant,
byte NewSkinIndex,
KFPawn KFP)
{
local int i;
if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
{
if( CurrentVariant.SkinVariations.length > 0 )
{
// Assign a skin to the attachment mesh as a material override
if ( NewSkinIndex < CurrentVariant.SkinVariations.length )
{
KFP.ThirdPersonAttachments[PawnAttachmentIndex].SetMaterial(
CurrentVariant.SkinMaterialID,
CurrentVariant.SkinVariations[NewSkinIndex].Skin);
}
else
{
`log("Out of bounds skin index for"@CurrentVariant.MeshName);
C.RemoveAttachmentMeshAndSkin(PawnAttachmentIndex, KFP);
}
}
else
{
// Use material specified in the mesh asset
for( i=0; i < KFP.ThirdPersonAttachments[PawnAttachmentIndex].GetNumElements(); i++ )
{
KFP.ThirdPersonAttachments[PawnAttachmentIndex].SetMaterial(i, none);
}
}
}
}
/** Called on owning client to change a cosmetic attachment or on other clients via replication */
static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentAttachmentMeshIndex,
byte CurrentAttachmentSkinIndex,
KFPawn KFP,
optional KFPlayerReplicationInfo KFPRI )
{
local string CharAttachmentMeshName;
local name CharAttachmentSocketName;
local bool bIsSkeletalAttachment;
local StaticMesh CharAttachmentStaticMesh;
local SkeletalMesh CharacterAttachmentSkelMesh;
local float MaxDrawDistance;
local StaticMeshComponent StaticAttachment;
local SkeletalMeshComponent SkeletalAttachment;
local SkeletalMeshSocket AttachmentSocket;
local vector AttachmentLocationRelativeToSocket, AttachmentScaleRelativeToSocket;
local rotator AttachmentRotationRelativeToSocket;
local int AttachmentSlotIndex;
if (KFP.WorldInfo.NetMode == NM_DedicatedServer)
return;
// Clear any previously attachments for the same slot
//DetachConflictingAttachments(CurrentAttachmentMeshIndex, KFP, KFPRI);
// Get a slot where this attachment could fit
AttachmentSlotIndex = C.GetAttachmentSlotIndex(CurrentAttachmentMeshIndex, KFP);
// Since cosmetic attachments are optional, do not choose index 0 if none is
// specified unlike the the head and body meshes
if ( C.CosmeticVariants.length > 0 && CurrentAttachmentMeshIndex < C.CosmeticVariants.length )
{
// Cache values from character info
CharAttachmentMeshName = C.CosmeticVariants[CurrentAttachmentMeshIndex].MeshName;
CharAttachmentSocketName = C.CosmeticVariants[CurrentAttachmentMeshIndex].SocketName;
MaxDrawDistance = C.CosmeticVariants[CurrentAttachmentMeshIndex].MaxDrawDistance;
AttachmentLocationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeTranslation;
AttachmentRotationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeRotation;
AttachmentScaleRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeScale;
bIsSkeletalAttachment = C.CosmeticVariants[CurrentAttachmentMeshIndex].bIsSkeletalAttachment;
// If it is a skeletal attachment, parent anim it to the body mesh
if( bIsSkeletalAttachment )
{
if( SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none )
{
// If previously attached and we could have changed outfits (e.g. local player UI) then re-validate
// required skeletal mesh socket. Must be after body mesh DLO, but before AttachComponent.
if ( KFP.IsLocallyControlled() )
{
if ( CharAttachmentSocketName != '' && KFP.Mesh.GetSocketByName(CharAttachmentSocketName) == None )
{
C.RemoveAttachmentMeshAndSkin(AttachmentSlotIndex, KFP, KFPRI);
return;
}
}
SkeletalAttachment = SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]);
}
else
{
SkeletalAttachment = new(KFP) class'SkeletalMeshComponent';
SkeletalAttachment.SetActorCollision(false, false);
KFP.ThirdPersonAttachments[AttachmentSlotIndex] = SkeletalAttachment;
}
// Load and assign skeletal mesh
CharacterAttachmentSkelMesh = SkeletalMesh(SafeLoadObject(CharAttachmentMeshName, class'SkeletalMesh'));
SkeletalAttachment.SetSkeletalMesh(CharacterAttachmentSkelMesh);
// Parent animation and LOD transitions to body mesh
SkeletalAttachment.SetParentAnimComponent(KFP.Mesh);
SkeletalAttachment.SetLODParent(KFP.Mesh);
SkeletalAttachment.SetScale(C.DefaultMeshScale);
SkeletalAttachment.SetCullDistance(MaxDrawDistance);
SkeletalAttachment.SetShadowParent(KFP.Mesh);
SkeletalAttachment.SetLightingChannels(KFP.PawnLightingChannel);
// Attach
KFP.AttachComponent(SkeletalAttachment);
}
// Otherwise (if static), attach to a socket on the body mesh
else
{
if( StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none )
{
StaticAttachment = StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]);
}
else
{
StaticAttachment = new(KFP) class'StaticMeshComponent';
StaticAttachment.SetActorCollision(false, false);
KFP.ThirdPersonAttachments[AttachmentSlotIndex] = StaticAttachment;
}
// Load and assign static mesh
CharAttachmentStaticMesh = StaticMesh(SafeLoadObject(CharAttachmentMeshName, class'StaticMesh'));
StaticAttachment.SetStaticMesh(CharAttachmentStaticMesh);
// Set properties
StaticAttachment.SetScale(C.DefaultMeshScale);
StaticAttachment.SetCullDistance(MaxDrawDistance);
StaticAttachment.SetShadowParent(KFP.Mesh);
StaticAttachment.SetLightingChannels(KFP.PawnLightingChannel);
// For static meshes, attach to given socket
AttachmentSocket = KFP.mesh.GetSocketByName(CharAttachmentSocketName);
KFP.mesh.AttachComponent(
StaticAttachment,
AttachmentSocket.BoneName,
AttachmentSocket.RelativeLocation + AttachmentLocationRelativeToSocket,
AttachmentSocket.RelativeRotation + AttachmentRotationRelativeToSocket,
AttachmentSocket.RelativeScale * AttachmentScaleRelativeToSocket);
}
// Update the pawn's attachment metadata
KFP.ThirdPersonAttachmentBitMask = KFP.ThirdPersonAttachmentBitMask | (1 << AttachmentSlotIndex);
KFP.ThirdPersonAttachmentSocketNames[AttachmentSlotIndex] = CharAttachmentSocketName;
SetAttachmentSkinMaterial(C,
AttachmentSlotIndex,
C.CosmeticVariants[CurrentAttachmentMeshIndex],
CurrentAttachmentSkinIndex,
KFP);
}
// Treat `CLEARED_ATTACHMENT_INDEX as special value (for client detachment)
if( CurrentAttachmentMeshIndex == `CLEARED_ATTACHMENT_INDEX )
{
C.RemoveAttachmentMeshAndSkin(AttachmentSlotIndex, KFP, KFPRI);
}
}
/**
* Removes any attachments that exist in the same socket or have overriding cases
* Network: Local Player
*/
static final function DetachConflictingAttachments( KFCharacterInfo_Human C, byte NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI)
{
local name NewAttachmentSocketName;
local int i, CurrentAttachmentIdx;
local ExtPlayerReplicationInfo EPRI;
EPRI = ExtPlayerReplicationInfo(KFPRI);
if ( EPRI==none || !EPRI.UsesCustomChar() )
return;
if ( C.CosmeticVariants.length > 0 &&
NewAttachmentMeshIndex < C.CosmeticVariants.length )
{
// The socket that this attachment requires
NewAttachmentSocketName = C.CosmeticVariants[NewAttachmentMeshIndex].SocketName;
for( i=0; i < `MAX_COSMETIC_ATTACHMENTS; i++ )
{
CurrentAttachmentIdx = EPRI.CustomCharacter.AttachmentMeshIndices[i];
if ( CurrentAttachmentIdx == `CLEARED_ATTACHMENT_INDEX )
continue;
// Remove the object if it is taking up our desired slot
if( KFP.ThirdPersonAttachmentSocketNames[i] != '' &&
KFP.ThirdPersonAttachmentSocketNames[i] == NewAttachmentSocketName )
{
C.RemoveAttachmentMeshAndSkin(i, KFP, KFPRI);
continue;
}
// Remove the object if it cannot exist at the same time as another equipped item
if( C.GetOverrideCase(CurrentAttachmentIdx, NewAttachmentMeshIndex) )
{
C.RemoveAttachmentMeshAndSkin(i, KFP, KFPRI);
continue;
}
// Check inverse override
if( C.GetOverrideCase(NewAttachmentMeshIndex, CurrentAttachmentIdx) )
{
C.RemoveAttachmentMeshAndSkin(i, KFP, KFPRI);
continue;
}
}
}
}
/** Assign an arm mesh and material to this pawn */
static final function SetFirstPersonArmsFromArch( KFCharacterInfo_Human C, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI )
{
local MaterialInstanceConstant M;
local ExtPlayerReplicationInfo EPRI;
local bool bCustom;
EPRI = ExtPlayerReplicationInfo(KFPRI);
if ( KFPRI == none )
{
`Warn("Does not have a KFPRI" @ C);
return;
}
bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false);
// First person arms mesh and skin are based on body mesh & skin.
// Index of 255 implies use index 0 (default).
C.SetArmsMeshAndSkin(
bCustom ? EPRI.CustomCharacter.BodyMeshIndex : KFPRI.RepCustomizationInfo.BodyMeshIndex,
bCustom ? EPRI.CustomCharacter.BodySkinIndex : KFPRI.RepCustomizationInfo.BodySkinIndex,
KFP);
// Hack fix for a material bug on KF2
if( bCustom && KFP.ArmsMesh.SkeletalMesh!=None && KFP.ArmsMesh.GetMaterial(0)!=None )
{
M = KFP.ArmsMesh.CreateAndSetMaterialInstanceConstant(0);
CloneMIC(M);
}
}

View File

@ -0,0 +1,34 @@
class ExtHUD_PlayerBackpack extends KFGFxHUD_PlayerBackpack;
var class<Ext_PerkBase> EPerkClass;
function UpdateGrenades()
{
local int CurrentGrenades;
local ExtPerkManager PM;
if(MyKFInvManager != none)
CurrentGrenades = MyKFInvManager.GrenadeCount;
//Update the icon the for grenade type.
if( ExtPlayerController(MyKFPC)!=None )
{
PM = ExtPlayerController(MyKFPC).ActivePerkManager;
if( PM!=None && PM.CurrentPerk!=None && EPerkClass!=PM.CurrentPerk.Class )
{
SetString("backpackGrenadeType", "img://"$PM.CurrentPerk.GrenadeWeaponDef.Static.GetImagePath());
EPerkClass = PM.CurrentPerk.Class;
}
}
// Update the grenades count value
if(CurrentGrenades != LastGrenades)
{
SetInt("backpackGrenades" , Min(CurrentGrenades,9));
LastGrenades = CurrentGrenades;
}
}
DefaultProperties
{
}

View File

@ -0,0 +1,71 @@
class ExtHUD_PlayerStatus extends KFGFxHUD_PlayerStatus;
var ExtPlayerController ExPC;
var class<Ext_PerkBase> ExLastPerkClass;
var string CurPerkPath;
function InitializeHUD()
{
Super.InitializeHUD();
ExPC = ExtPlayerController(MyPC);
}
function UpdatePerk()
{
local int CurrentPerkLevel,CurrentPerkEXP;
local Ext_PerkBase CurrentPerk;
if( ExPC == none || ExPC.ActivePerkManager==None || ExPC.ActivePerkManager.CurrentPerk==None )
return;
CurrentPerk = ExPC.ActivePerkManager.CurrentPerk;
CurrentPerkLevel = CurrentPerk.CurrentLevel;
CurrentPerkEXP = CurrentPerk.CurrentEXP;
// Update the perk class.
if( ( ExLastPerkClass != CurrentPerk.Class ) || ( LastPerkLevel != CurrentPerkLevel ) )
{
CurPerkPath = CurrentPerk.GetPerkIconPath(CurrentPerkLevel);
SetString("playerPerkIcon" , CurPerkPath);
SetInt("playerPerkXPPercent", CurrentPerk.GetProgressPercent() * 100.f );
if( LastPerkLevel != CurrentPerkLevel && ExLastPerkClass==CurrentPerk.Class )
{
SetBool("bLevelUp", true);
ShowXPBark(CurrentPerkEXP-LastEXPValue,CurPerkPath,true);
}
ExLastPerkClass = CurrentPerk.class;
SetInt("playerPerkLevel" , CurrentPerkLevel);
LastPerkLevel = CurrentPerkLevel;
LastEXPValue = CurrentPerkEXP;
}
else if( LastEXPValue!=CurrentPerkEXP )
{
SetBool("bLevelUp", false);
SetInt("playerPerkXPPercent", CurrentPerk.GetProgressPercent() * 100.f );
ShowXPBark(CurrentPerkEXP-LastEXPValue,CurPerkPath,true);
LastEXPValue = CurrentPerkEXP;
}
}
function ShowXPBark( int DeltaXP, string IconPath, bool bIsCurrentPerk )
{
ActionScriptVoid("showXPBark");
}
function UpdateHealth()
{
if( MyPC.Pawn == none )
{
LastHealth = 0;
SetInt("playerHealth" , LastHealth);
}
else if( LastHealth != MyPC.Pawn.Health )
{
LastHealth = MyPC.Pawn.Health;
SetInt("playerHealth" , LastHealth);
}
}
defaultproperties
{
}

View File

@ -0,0 +1,61 @@
class ExtHUD_SpectatorInfo extends KFGFxHUD_SpectatorInfo;
var class<Ext_PerkBase> ExtLastPerkClass;
var bool bUnsetInfo;
function LocalizeText()
{
local GFxObject TempObject;
TempObject = CreateObject("Object");
TempObject.SetString("prevPlayer", "FREE CAMERA");
TempObject.SetString("nextPlayer", PrevPlayerString);
TempObject.SetString("changeCamera", ChangeCameraString);
SetObject("localizedText", TempObject);
}
function UpdateSpectateeInfo(optional bool bForceUpdate)
{
local ExtPlayerReplicationInfo E;
E = ExtPlayerReplicationInfo(SpectatedKFPRI);
if( !GetPC().IsSpectating() || E==None )
{
if( !bUnsetInfo )
{
SetVisible(false);
bUnsetInfo = true;
}
return;
}
// Update the perk class.
if( ExtLastPerkClass!=E.ECurrentPerk || LastPerkLevel!=E.ECurrentPerkLevel || bForceUpdate || bUnsetInfo )
{
LastPerkLevel = E.ECurrentPerkLevel;
ExtLastPerkClass = E.ECurrentPerk;
UpdatePlayerInfo(bForceUpdate);
bUnsetInfo = false;
}
}
function UpdatePlayerInfo(optional bool bForceUpdate)
{
local GFxObject TempObject;
TempObject = CreateObject("Object");
TempObject.SetString("playerName", SpectatedKFPRI.GetHumanReadableName());
if( ExtLastPerkClass!=None )
{
TempObject.SetString("playerPerk", SpectatedKFPRI.CurrentPerkClass.default.LevelString @LastPerkLevel @ExtLastPerkClass.default.PerkName );
TempObject.SetString("iconPath", ExtLastPerkClass.Static.GetPerkIconPath(LastPerkLevel));
}
else TempObject.SetString("playerPerk","No perk");
SetObject("playerData", TempObject);
SetVisible(true);
}
defaultproperties
{
}

View File

@ -0,0 +1,56 @@
class ExtHUD_WaveInfo extends KFGFxHUD_WaveInfo;
function TickHud(float DeltaTime)
{
local int i;
if(KFGRI == none)
KFGRI = KFGameReplicationInfo(GetPC().WorldInfo.GRI);
else
{
if(KFGRI.bTraderIsOpen)
{
i = KFGRI.GetTraderTimeRemaining();
if(LastTraderTimeRemaining != i)
{
SetInt("remainingTraderTime" ,i);
LastTraderTimeRemaining = i;
}
}
else
{
i = KFGRI.IsFinalWave() ? INDEX_NONE : Max(KFGRI.AIRemaining,0);
if(LastZEDCount != i)
{
SetInt("remainingZEDs" ,i);
LastZEDCount = i;
}
}
// Max # of waves.
if(LastWaveMax != KFGRI.WaveMax)
{
LastWaveMax = KFGRI.WaveMax;
SetInt("maxWaves" ,LastWaveMax-1);
}
// Current wave we're on.
if( LastWave!=KFGRI.WaveNum )
{
LastWave = KFGRI.WaveNum;
if( LastWave>LastWaveMax )
{
SetInt("currentWave",0); // Force text to refresh.
SetString("finalText", "END");
}
SetInt("currentWave",Min(LastWave,LastWaveMax));
}
}
}
function UpdateWaveCount();
DefaultProperties
{
LastWave=-1
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
class ExtInventoryManager extends KFInventoryManager;
// Dosh spamming barrier.
var transient float MoneyTossTime;
var transient byte MoneyTossCount;
reliable server function ServerThrowMoney()
{
if( MoneyTossTime>WorldInfo.TimeSeconds )
{
if( MoneyTossCount>=10 )
return;
++MoneyTossCount;
MoneyTossTime = FMax(MoneyTossTime,WorldInfo.TimeSeconds+0.5);
}
else
{
MoneyTossCount = 0;
MoneyTossTime = WorldInfo.TimeSeconds+1;
}
Super.ServerThrowMoney();
}

View File

@ -0,0 +1,632 @@
class ExtMenu_Gear extends KFGFxObject_Menu;
var ExtPlayerReplicationInfo ExtPRI;
var KFGFxObject_TraderItems TraderItems;
var KFGFxGearContainer_PerksSelection PerkSelectionContainer;
var KFCharacterInfo_Human CurrentCharInfo;
var string CharInfoPath;
var int CurrentPerkIndex;
var array<class<KFWeaponDefinition> > CurrentWearponDefList;
var array<Emote> EmoteList;
var bool bWaitingCharList,bIsCustomChar;
function InitializeMenu( KFGFxMoviePlayer_Manager InManager )
{
super(KFGFxObject_Menu).InitializeMenu(InManager);
LocalizeText();
EmoteList = class'KFEmoteList'.static.GetEmoteArray();
InitCharacterMenu();
TraderItems = KFGameReplicationInfo( GetPC().WorldInfo.GRI ).TraderItems;
}
function InitCharacterMenu()
{
ExtPRI = ExtPlayerReplicationInfo(GetPC().PlayerReplicationInfo);
if( ExtPRI!=None && ExtPRI.bClientInitChars )
CharListRecieved();
else if( ExtPRI==None )
{
if( GetPC().PlayerReplicationInfo!=None ) // Faulty mod setup.
{
bWaitingCharList = true;
return;
}
GetPC().SetTimer(0.1,false,'InitCharacterMenu',Self);
}
else
{
ExtPRI.OnCharListDone = CharListRecieved;
bWaitingCharList = true;
}
}
event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget)
{
switch(WidgetName)
{
case 'perkSelectionContainer':
if ( PerkSelectionContainer == none )
{
PerkSelectionContainer = KFGFxGearContainer_PerksSelection( Widget );
PerkSelectionContainer.Initialize(self);
}
break;
}
return true;
}
function OnOpen()
{
local PlayerController PC;
PC = GetPC();
if( PC == none )
return;
// @hack: moved from KFGfxMoviePlayer_Manager because this causes a crash while
// bink (e.g. KFII-25456) are playing. Don't use HandleInputAxis with Bink! (for now) :)
GetGameViewportClient().HandleInputAxis = OnAxisModified;
if ( PC.PlayerReplicationInfo.bReadyToPlay && PC.WorldInfo.GRI.bMatchHasBegun )
{
// Players cannot change characters if they are in a game
SetBool("characterButtonEnabled", false);
}
}
function LocalizeText()
{
local GFxObject LocalizedObject;
LocalizedObject = CreateObject("Object");
LocalizedObject.SetString("header", class'KFGFxMenu_Gear'.Default.GearHeaderString);
LocalizedObject.SetString("listButton", class'KFGFxMenu_Gear'.Default.BackString);
LocalizedObject.SetString("bioStringText", class'KFGFxMenu_Gear'.Default.BioString);
LocalizedObject.SetString("charactersString", class'KFGFxMenu_Gear'.Default.CharacterString);
LocalizedObject.SetString("headsString", class'KFGFxMenu_Gear'.Default.HeadString);
LocalizedObject.SetString("emoteString", Class'KFLocalMessage_VoiceComms'.default.VoiceCommsOptionStrings[8]);
LocalizedObject.SetString("bodiesString", class'KFGFxMenu_Gear'.Default.BodyString);
LocalizedObject.SetString("skinsString", class'KFGFxMenu_Gear'.Default.SkinsString);
LocalizedObject.SetString("attachmentsString", class'KFGFxMenu_Gear'.Default.AttachmentsString);
SetObject("localizeText", LocalizedObject);
}
simulated function CharListRecieved()
{
UpdateCharacterList();
UpdateGear();
}
function UpdateEmoteList()
{
local byte ItemIndex, i;
local GFxObject DataProvider, SlotObject;
local string TexturePath;
ItemIndex = 0;
DataProvider = CreateArray();
for (i = 0; i < EmoteList.length; i++)
{
if ( class'KFEmoteList'.static.GetUnlockedEmote(EmoteList[i].Id) != 'NONE')
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
SlotObject.SetString("label", Localize(EmoteList[i].ItemName, "EmoteName", class'KFGFxMenu_Gear'.Default.KFCharacterInfoString));
TexturePath = "img://"$EmoteList[i].IconPath;
SlotObject.SetBool("enabled", true);
SlotObject.SetString("source", TexturePath);
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
else
{
//`log(MyKFPRI.EmoteList[i] @ "is not purchased.");
}
}
SetObject("emoteArray", DataProvider);
}
function UpdateCharacterList()
{
local byte i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local string TexturePath;
bWaitingCharList = false;
ItemIndex = 0;
DataProvider = CreateArray();
for( i=0; i<ExtPRI.CharacterArchetypes.length; i++)
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
SlotObject.SetString("label", Localize(String(ExtPRI.CharacterArchetypes[i].Name), "CharacterName", class'KFGFxMenu_Gear'.Default.KFCharacterInfoString));
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(ExtPRI.CharacterArchetypes[i].DefaultHeadPortrait);
SlotObject.SetString("source", TexturePath);
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
for( i=0; i<ExtPRI.CustomCharList.length; i++)
{
if( !ExtPRI.IsClientCharLocked(ExtPRI.CharacterArchetypes.length+i) )
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", (ExtPRI.CharacterArchetypes.length+i));
SlotObject.SetString("label", Repl(string(ExtPRI.CustomCharList[i].Char.Name),"_"," "));
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(ExtPRI.CustomCharList[i].Char.DefaultHeadPortrait);
SlotObject.SetString("source", TexturePath);
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
}
SetObject("characterArray", DataProvider);
}
function UpdateGear()
{
if( bWaitingCharList )
return;
CurrentCharInfo = ExtPRI.GetSelectedArch();
bIsCustomChar = ExtPRI.ReallyUsingCustomChar();
CharInfoPath = String(CurrentCharInfo.Name);
// Set the list of usable bodies for this character
UpdateMeshList(class'KFGFxMenu_Gear'.Default.BodyMeshKey, class'KFGFxMenu_Gear'.Default.BodySkinKey, CurrentCharInfo.BodyVariants, "bodyArray");
// Set the list of usable heads for this character
UpdateMeshList(class'KFGFxMenu_Gear'.Default.HeadMeshKey, class'KFGFxMenu_Gear'.Default.HeadSkinKey, CurrentCharInfo.HeadVariants, "headsArray");
// Set the list of usable attachments for this character
UpdateAttachmentsList(CurrentCharInfo.CosmeticVariants);
UpdateEmoteList();
SetCurrentCharacterButtons();
}
final function string GetMenuName( Object Obj )
{
return Obj==None ? "Empty" : Repl(string(Obj.Name),"_"," ");
}
final function string GetMenuNameStr( string ObjName )
{
local int i;
i = InStr(ObjName,".",true);
if( i!=-1 )
ObjName = Mid(ObjName,i+1);
return Repl(ObjName,"_"," ");
}
function UpdateMeshList(string OutfitKey, string SkinKey, array<OutfitVariants> Outfits, string DataArrayString)
{
local byte i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local string TexturePath;
local OutfitVariants Outfit;
ItemIndex = 0;
DataProvider = CreateArray();
for (i = 0; i < Outfits.length; i++)
{
Outfit = Outfits[i];
if( bIsCustomChar )
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
SlotObject.SetString("label", GetMenuNameStr(Outfit.MeshName));
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(Outfit.UITexture);
SlotObject.SetString("source", TexturePath);
UpdateVariants( OutfitKey, SkinKey, Outfit.SkinVariations, i, SlotObject );
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
else
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
SlotObject.SetString("label", Localize(CharInfoPath, OutfitKey$i, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString));
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(Outfit.UITexture);
SlotObject.SetString("source", TexturePath);
UpdateVariants( OutfitKey, SkinKey, Outfit.SkinVariations, i, SlotObject );
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
}
SetObject(DataArrayString, DataProvider);
}
function UpdateAttachmentsList(array<AttachmentVariants> Attachments)
{
local byte i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local string TexturePath;
local AttachmentVariants Variant;
ItemIndex = 0;
DataProvider = CreateArray();
// Insert blank object
SlotObject = CreateObject( "Object" );
SlotObject.SetString("label", class'KFGFxMenu_Gear'.Default.NoneString);
SlotObject.SetString("source", "img://"$class'KFGFxMenu_Gear'.Default.ClearImagePath);
SlotObject.SetBool("enabled", true);
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
for (i = 0; i < Attachments.length; i++)
{
Variant = Attachments[i];
if( bIsCustomChar )
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
SlotObject.SetString("label", GetMenuNameStr(Variant.MeshName));
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(Variant.UITexture);
SlotObject.SetString("source", TexturePath);
UpdateVariants( class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentSkinKey, Variant.SkinVariations, i, SlotObject );
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
else
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
SlotObject.SetString("label", Localize(CharInfoPath, class'KFGFxMenu_Gear'.Default.AttachmentKey$i, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString));
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(Variant.UITexture);
SlotObject.SetString("source", TexturePath);
UpdateVariants( class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentSkinKey, Variant.SkinVariations, i, SlotObject );
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
}
SetObject("attachmentsArray", DataProvider);
}
function UpdateVariants(string OutfitKey, string KeyName, out array<SkinVariant> SkinVariations, int OutfitIndex, out GFxObject MeshObject)
{
local byte i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local SkinVariant Skin;
local string SectionPath;
local string TexturePath;
ItemIndex = 0;
DataProvider = CreateArray();
SectionPath = CharInfoPath$"."$OutfitKey$OutfitIndex;
for (i = 0; i < SkinVariations.length; i++)
{
Skin = SkinVariations[i];
if( bIsCustomChar )
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
SlotObject.SetString("label", GetMenuName(Skin.Skin));
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(Skin.UITexture);
SlotObject.SetString("source", TexturePath);
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
else
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
SlotObject.SetString("label", Localize(SectionPath, KeyName$i, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString));
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(Skin.UITexture);
SlotObject.SetString("source", TexturePath);
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
}
MeshObject.SetObject("skinInfo", DataProvider);
}
function SetCurrentCharacterButtons()
{
local bool bCustom;
local GFxObject DataObject;
bCustom = ExtPRI.UsesCustomChar();
DataObject = CreateObject("Object");
DataObject.SetString( "selectedCharacter", (bIsCustomChar ? Repl(string(CurrentCharInfo.Name),"_"," ") : Localize(CharInfoPath, "CharacterName", class'KFGFxMenu_Gear'.Default.KFCharacterInfoString)) );
DataObject.SetString( "characterBio", (bIsCustomChar ? Repl(CurrentCharInfo.ArmMeshPackageName,"|","\n") : Localize(CharInfoPath, "Description", class'KFGFxMenu_Gear'.Default.KFCharacterInfoString)) );
DataObject.SetInt( "selectedCharacterIndex", bCustom ? ExtPRI.CustomCharacter.CharacterIndex : ExtPRI.RepCustomizationInfo.CharacterIndex );
SetObject( "selectedCharacter", DataObject);
//set head
SetGearButtons(bCustom ? ExtPRI.CustomCharacter.HeadMeshIndex : ExtPRI.RepCustomizationInfo.HeadMeshIndex, bCustom ? ExtPRI.CustomCharacter.HeadSkinIndex : ExtPRI.RepCustomizationInfo.HeadSkinIndex, class'KFGFxMenu_Gear'.Default.HeadMeshKey, class'KFGFxMenu_Gear'.Default.HeadSkinKey, class'KFGFxMenu_Gear'.Default.HeadFunctionKey);
//set body
SetGearButtons(bCustom ? ExtPRI.CustomCharacter.BodyMeshIndex : ExtPRI.RepCustomizationInfo.BodyMeshIndex, bCustom ? ExtPRI.CustomCharacter.BodySkinIndex : ExtPRI.RepCustomizationInfo.BodySkinIndex, class'KFGFxMenu_Gear'.Default.BodyMeshKey, class'KFGFxMenu_Gear'.Default.BodySkinKey, class'KFGFxMenu_Gear'.Default.BodyFunctionKey);
//set attachments
SetAttachmentButtons(class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentFunctionKey);
SetEmoteButton();
}
function SetEmoteButton()
{
local GFxObject DataObject;
local int EmoteIndex;
EmoteIndex = class'KFEmoteList'.static.GetEmoteIndex( class'KFEmoteList'.static.GetEquippedEmoteId());
DataObject = CreateObject("Object");
if(EmoteIndex == 255)
{
DataObject.SetString( "selectedEmote", "");
DataObject.SetInt( "selectedEmoteIndex", 0 );
}
else
{
DataObject.SetString( "selectedEmote", Localize(EmoteList[EmoteIndex].ItemName, "EmoteName", class'KFGFxMenu_Gear'.Default.KFCharacterInfoString));
DataObject.SetInt( "selectedEmoteIndex", 0 );
}
SetObject("selectedEmote", DataObject);
}
/** Update the labels for our gear buttons */
function SetGearButtons(byte MeshIndex, byte SkinIndex, string MeshKey, string SkinKey, string sectionFunctionName)
{
local string SectionPath;
local string CurrentMesh;
local string SkinName, MeshName;
local GFxObject DataObject;
if( bWaitingCharList )
return;
DataObject = CreateObject("Object");
if(MeshIndex == `CLEARED_ATTACHMENT_INDEX)
{
DataObject.SetString( sectionFunctionName, class'KFGFxMenu_Gear'.Default.NoneString );
}
else if( bIsCustomChar )
{
if( MeshKey==class'KFGFxMenu_Gear'.Default.HeadMeshKey )
{
SkinName = GetMenuName(CurrentCharInfo.HeadVariants[MeshIndex].SkinVariations[SkinIndex].Skin);
MeshName = GetMenuNameStr(CurrentCharInfo.HeadVariants[MeshIndex].MeshName);
}
else
{
SkinName = GetMenuName(CurrentCharInfo.BodyVariants[MeshIndex].SkinVariations[SkinIndex].Skin);
MeshName = GetMenuNameStr(CurrentCharInfo.BodyVariants[MeshIndex].MeshName);
}
DataObject.SetString( sectionFunctionName, MeshName @"\n" @SkinName );
}
else
{
CurrentMesh = MeshKey$MeshIndex;
SectionPath = CharInfoPath$"."$CurrentMesh;
SkinName = Localize(SectionPath, SkinKey$SkinIndex, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString);
MeshName = Localize(CharInfoPath, CurrentMesh, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString);
DataObject.SetString( sectionFunctionName, MeshName @"\n" @SkinName );
}
DataObject.SetInt( (sectionFunctionName$"Index"), MeshIndex);
DataObject.SetInt( (sectionFunctionName$"SkinIndex"), SkinIndex);
SetObject( sectionFunctionName, DataObject);
}
/** Update the labels for our currently equipped attachments */
function SetAttachmentButtons(string AttachmentMeshKey, string sectionFunctionName)
{
local string CurrentMesh, FinishedString;
local GFxObject DataObject;
local byte i, AttachmentIndex;
local bool bCustom;
if( bWaitingCharList )
return;
bCustom = ExtPRI.UsesCustomChar();
DataObject = CreateObject("Object");
for(i = 0; i < `MAX_COSMETIC_ATTACHMENTS; i++)
{
AttachmentIndex = bCustom ? ExtPRI.CustomCharacter.AttachmentMeshIndices[i] : ExtPRI.RepCustomizationInfo.AttachmentMeshIndices[i];
if( AttachmentIndex == `CLEARED_ATTACHMENT_INDEX )
{
FinishedString $= "----"$"\n";
}
else
{
CurrentMesh = AttachmentMeshKey$AttachmentIndex;
FinishedString $= (bIsCustomChar ? GetMenuNameStr(CurrentCharInfo.CosmeticVariants[AttachmentIndex].MeshName) : Localize(CharInfoPath, CurrentMesh, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString))$"\n";
}
}
DataObject.SetString( sectionFunctionName, FinishedString );
SetObject( sectionFunctionName, DataObject);
}
event OnClose()
{
local PlayerController PC;
super.OnClose();
GetGameViewportClient().HandleInputAxis = none;
if ( class'WorldInfo'.static.IsMenuLevel() )
{
Manager.ManagerObject.SetBool("backgroundVisible", true);
}
// If we are alive, in game, with a playable pawn. switch back to first person view when leaving this menu
PC = GetPC();
if( PC != none && PC.WorldInfo.GRI.bMatchHasBegun && PC.Pawn != none && !PC.Pawn.IsA('KFPawn_Customization') )
{
PC.ServerCamera( 'FirstPerson' );
}
}
event bool OnAxisModified( int ControllerId, name Key, float Delta, float DeltaTime, bool bGamepad )
{
if ( GetPC().PlayerInput.bUsingGamepad )
{
if ( Key == 'XboxTypeS_RightX' && Abs(Delta) > class'KFGFxMenu_Gear'.Default.ControllerRotationThreshold)
{
Callback_RotateCamera(Delta * class'KFGFxMenu_Gear'.Default.ControllerRotationRate);
}
}
return false;
}
//==============================================================
// ActionScript Callbacks
//==============================================================
function Callback_Emote(byte Index)
{
local KFPlayerController KFPC;
KFPC = KFPlayerController(GetPC());
if( KFPC != none )
{
class'KFEmoteList'.static.SaveEquippedEmote(EmoteList[Index].ID);
if ( KFPawn_Customization(KFPC.Pawn) != none )
{
KFPawn_Customization(KFPC.Pawn).PlayEmoteAnimation();
}
}
SetEmoteButton();
}
function Callback_RotateCamera( int RotationDirection )
{
local KFPlayerCamera PlayerCamera;
PlayerCamera = KFPlayerCamera( GetPC().PlayerCamera );
if ( PlayerCamera != none )
PlayerCamera.CustomizationCam.RotatedCamera( RotationDirection );
}
function Callback_EndRotateCamera()
{
local KFPlayerCamera PlayerCamera;
PlayerCamera = KFPlayerCamera( GetPC().PlayerCamera );
if ( PlayerCamera != none )
PlayerCamera.CustomizationCam.StartFadeRotation();
}
function Callback_Weapon( int ItemIndex, int SkinIndex )
{
local KFPawn_Customization KFP;
KFP = KFPawn_Customization(GetPC().Pawn);
if(KFP != none)
KFP.AttachWeaponByItemDefinition(SkinIndex);
}
function Callback_BodyCamera()
{
if ( KFPlayerCamera( GetPC().PlayerCamera ) != none )
KFPlayerCamera( GetPC().PlayerCamera ).CustomizationCam.SetBodyView( 0 );
}
function Callback_HeadCamera()
{
if ( KFPlayerCamera( GetPC().PlayerCamera ) != none )
KFPlayerCamera( GetPC().PlayerCamera ).CustomizationCam.SetBodyView( 1 );
}
function Callback_Character(byte Index)
{
ExtPRI.ChangeCharacter(Index,!ExtPRI.UsesCustomChar());
UpdateGear();
}
function Callback_Head( byte MeshIndex, byte SkinIndex )
{
if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server.
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
ExtPRI.UpdateCustomization(CO_Head, MeshIndex, SkinIndex);
SetGearButtons(MeshIndex, SkinIndex, class'KFGFxMenu_Gear'.Default.HeadMeshKey, class'KFGFxMenu_Gear'.Default.HeadSkinKey, class'KFGFxMenu_Gear'.Default.HeadFunctionKey);
}
function Callback_Body( byte MeshIndex, byte SkinIndex )
{
if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server.
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
ExtPRI.UpdateCustomization(CO_Body, MeshIndex, SkinIndex);
// When assigning a new body mesh we may need to remove certain attachments
// refresh filters, and update the equipped accessories list
UpdateAttachmentsList(CurrentCharInfo.CosmeticVariants);
SetAttachmentButtons(class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentFunctionKey);
SetGearButtons(MeshIndex, SkinIndex, class'KFGFxMenu_Gear'.Default.BodyMeshKey, class'KFGFxMenu_Gear'.Default.BodySkinKey, class'KFGFxMenu_Gear'.Default.BodyFunctionKey);
}
function Callback_Attachment( byte MeshIndex, byte SkinIndex )
{
local int SlotIndex;
local KFPawn KFP;
if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server.
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
KFP = KFPawn(GetPC().Pawn);
if( KFP!=None )
{
if( MeshIndex==`CLEARED_ATTACHMENT_INDEX )
ExtPRI.RemoveAttachments();
else
{
class'ExtCharacterInfo'.Static.DetachConflictingAttachments(CurrentCharInfo, MeshIndex, KFP, ExtPRI);
SlotIndex = CurrentCharInfo.GetAttachmentSlotIndex(MeshIndex, KFP);
ExtPRI.UpdateCustomization(CO_Attachment, MeshIndex, SkinIndex, SlotIndex);
}
SetAttachmentButtons(class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentFunctionKey);
}
}
defaultproperties
{
SubWidgetBindings.Add((WidgetName="customizationComponent",WidgetClass=class'KFGFxObject_Container'))
SubWidgetBindings.Add((WidgetName="perkSelectionContainer",WidgetClass=class'KFGFxGearContainer_PerksSelection'))
}

View File

@ -0,0 +1,78 @@
class ExtMenu_Perks extends KFGFxMenu_Perks;
var ExtPlayerController ExtKFPC;
var Ext_PerkBase ExtPrevPerk;
function OnOpen()
{
KFPC = KFPlayerController( GetPC() );
if( ExtKFPC == none )
ExtKFPC = ExtPlayerController(KFPC);
if( ExtKFPC.ActivePerkManager==None )
{
ExtKFPC.SetTimer(0.25,true,'OnOpen',Self);
return;
}
ExtKFPC.ClearTimer('OnOpen',Self);
if( ExtPrevPerk==None )
ExtPrevPerk = ExtKFPC.ActivePerkManager.CurrentPerk;
ExUpdateContainers(ExtPrevPerk);
SetBool( "locked", true);
}
final function ExUpdateContainers( Ext_PerkBase PerkClass )
{
LastPerkLevel = PerkClass.CurrentLevel;
if ( ExtPerksContainer_Header(HeaderContainer)!=none )
ExtPerksContainer_Header(HeaderContainer).ExUpdatePerkHeader( PerkClass );
if ( ExtPerksContainer_Details(DetailsContainer)!=none )
{
ExtPerksContainer_Details(DetailsContainer).ExUpdateDetails( PerkClass );
ExtPerksContainer_Details(DetailsContainer).ExUpdatePassives( PerkClass );
}
if ( SelectionContainer != none )
SelectionContainer.UpdatePerkSelection(ExtKFPC.ActivePerkManager.UserPerks.Find(PerkClass));
}
function CheckTiersForPopup();
event OnClose()
{
ExtPrevPerk = None;
if ( ExtKFPC != none )
ExtKFPC.ClearTimer('OnOpen',Self);
super.OnClose();
}
function PerkChanged( byte NewPerkIndex, bool bClickedIndex)
{
ExUpdateContainers(ExtPrevPerk);
}
function OneSecondLoop()
{
if( ExtPrevPerk!=None && LastPerkLevel!=ExtPrevPerk.CurrentLevel )
ExUpdateContainers(ExtPrevPerk);
}
function UpdateLock();
function SavePerkData();
function Callback_PerkSelected(byte NewPerkIndex, bool bClickedIndex)
{
ExtPrevPerk = ExtKFPC.ActivePerkManager.UserPerks[NewPerkIndex];
ExUpdateContainers(ExtPrevPerk);
ExtKFPC.PendingPerkClass = ExtPrevPerk.Class;
ExtKFPC.SwitchToPerk(ExtPrevPerk.Class);
}
function Callback_SkillSelectionOpened();
defaultproperties
{
SubWidgetBindings(0)=(WidgetClass=Class'ExtPerksContainer_Selection')
SubWidgetBindings(1)=(WidgetClass=Class'ExtPerksContainer_Header')
SubWidgetBindings(3)=(WidgetClass=Class'ExtPerksContainer_Details')
}

View File

@ -0,0 +1,54 @@
class ExtMenu_Trader extends KFGFxMenu_Trader;
var ExtPlayerController ExtKFPC;
var Ext_PerkBase ExLastPerkClass;
function InitializeMenu( KFGFxMoviePlayer_Manager InManager )
{
Super.InitializeMenu(InManager);
ExtKFPC = ExtPlayerController ( GetPC() );
}
function int GetPerkIndex()
{
return (ExtKFPC.ActivePerkManager!=None ? Max(ExtKFPC.ActivePerkManager.UserPerks.Find(ExtKFPC.ActivePerkManager.CurrentPerk),0) : 0);
}
function UpdatePlayerInfo()
{
if( ExtKFPC != none && PlayerInfoContainer != none )
{
PlayerInfoContainer.SetPerkInfo();
PlayerInfoContainer.SetPerkList();
if( ExtKFPC.ActivePerkManager!=None && ExtKFPC.ActivePerkManager.CurrentPerk!=ExLastPerkClass)
{
ExLastPerkClass = ExtKFPC.ActivePerkManager.CurrentPerk;
OnPerkChanged(GetPerkIndex());
}
RefreshItemComponents();
}
}
function Callback_PerkChanged(int PerkIndex)
{
ExtKFPC.PendingPerkClass = ExtKFPC.ActivePerkManager.UserPerks[PerkIndex].Class;
ExtKFPC.SwitchToPerk(ExtKFPC.PendingPerkClass);
if( PlayerInventoryContainer != none )
{
PlayerInventoryContainer.UpdateLock();
}
UpdatePlayerInfo();
// Refresht he UI
RefreshItemComponents();
}
defaultproperties
{
SubWidgetBindings.Remove((WidgetName="filterContainer",WidgetClass=class'KFGFxTraderContainer_Filter'))
SubWidgetBindings.Add((WidgetName="filterContainer",WidgetClass=class'ExtTraderContainer_Filter'))
SubWidgetBindings.Remove((WidgetName="shopContainer",WidgetClass=class'KFGFxTraderContainer_Store'))
SubWidgetBindings.Add((WidgetName="shopContainer",WidgetClass=class'ExtTraderContainer_Store'))
SubWidgetBindings.Remove((WidgetName="playerInfoContainer",WidgetClass=class'KFGFxTraderContainer_PlayerInfo'))
SubWidgetBindings.Add((WidgetName="playerInfoContainer",WidgetClass=class'ExtTraderContainer_PlayerInfo'))
}

View File

@ -0,0 +1,108 @@
Class ExtMoviePlayer_HUD extends KFGFxMoviePlayer_HUD;
function TickHud(float DeltaTime)
{
local PlayerController PC;
PC = GetPC();
if( PC!=none && PC.PlayerInput!=None )
Super.TickHud(DeltaTime);
}
final function ShowKillMessageX(PlayerReplicationInfo PRI1, PlayerReplicationInfo PRI2, optional string VictimStr, optional bool bDeathMessage = false, optional class<Pawn> PawnOther )
{
local GFxObject DataObject;
local bool bHumanDeath;
local string KilledName, KillerName, KilledIconpath, KillerIconPath;
local string KillerTextColor, KilledTextColor;
if(KFPC == none)
return;
if( KFGXHUDManager != none )
{
if(PawnOther != none)
{
if( bDeathMessage )
{
KillerTextColor = ZEDTeamTextColor;
KillerName = class'KFExtendedHUD'.Static.GetNameOf(PawnOther);
}
else
{
KilledName = class'KFExtendedHUD'.Static.GetNameOf(PawnOther);
bHumanDeath = false;
}
}
if( (PawnOther==None || !bDeathMessage) && PRI1 != none)
{
if(PRI1.GetTeamNum() == 255)
{
KillerTextColor = ZEDTeamTextColor;
KillerIconpath = "img://"$class'KFPerk_Monster'.static.GetPerkIconPath();
}
else
{
KillerTextColor = HumanTeamTextColor;
if( ExtPlayerReplicationInfo(PRI1)!=None && ExtPlayerReplicationInfo(PRI1).ECurrentPerk!=None )
KillerIconpath = ExtPlayerReplicationInfo(PRI1).ECurrentPerk.static.GetPerkIconPath(0);
}
KillerName = PRI1.PlayerName;
}
if(PRI2 != none)
{
if(PRI2.GetTeamNum() == class'KFTeamInfo_Human'.default.TeamIndex)
{
bHumanDeath = true;
KilledTextColor = HumanTeamTextColor;
}
else
{
KilledTextColor = ZEDTeamTextColor;
bHumanDeath = false;
}
KilledName = PRI2.PlayerName;
if( ExtPlayerReplicationInfo(PRI2)!=None && ExtPlayerReplicationInfo(PRI2).ECurrentPerk!=None )
KilledIconpath = ExtPlayerReplicationInfo(PRI2).ECurrentPerk.static.GetPerkIconPath(0);
}
else if( VictimStr!="" )
{
KilledTextColor = HumanTeamTextColor;
KilledIconpath = "img://"$class'KFPerk_Monster'.static.GetPerkIconPath();
bHumanDeath = false;
KilledName = VictimStr;
}
DataObject = CreateObject("Object");
DataObject.SetBool("humanDeath", bHumanDeath);
DataObject.SetString("killedName", KilledName);
DataObject.SetString("killedTextColor", KilledTextColor);
DataObject.SetString("killedIcon", KilledIconpath);
DataObject.SetString("killerName", KillerName);
DataObject.SetString("killerTextColor", KillerTextColor);
DataObject.SetString("killerIcon", KillerIconpath);
//temp remove when rest of design catches up
DataObject.SetString("text", KillerName@KilledName);
KFGXHUDManager.SetObject("newBark", DataObject);
}
}
defaultproperties
{
WidgetBindings.Remove((WidgetName="SpectatorInfoWidget",WidgetClass=class'KFGFxHUD_SpectatorInfo'))
WidgetBindings.Add((WidgetName="SpectatorInfoWidget",WidgetClass=class'ExtHUD_SpectatorInfo'))
WidgetBindings.Remove((WidgetName="PlayerStatWidgetMC",WidgetClass=class'KFGFxHUD_PlayerStatus'))
WidgetBindings.Add((WidgetName="PlayerStatWidgetMC",WidgetClass=class'ExtHUD_PlayerStatus'))
WidgetBindings.Remove((WidgetName="PlayerBackpackWidget",WidgetClass=class'KFGFxHUD_PlayerBackpack'))
WidgetBindings.Add((WidgetName="PlayerBackpackWidget",WidgetClass=class'ExtHUD_PlayerBackpack'))
WidgetBindings.Remove((WidgetName="WaveInfoContainer",WidgetClass=class'KFGFxHUD_WaveInfo'))
WidgetBindings.Add((WidgetName="WaveInfoContainer",WidgetClass=class'ExtHUD_WaveInfo'))
WidgetBindings.Remove((WidgetName="bossHealthBar", WidgetClass=class'KFGFxWidget_BossHealthBar'))
WidgetBindings.Add((WidgetName="bossHealthBar", WidgetClass=class'ExtWidget_BossHealthBar'))
}

View File

@ -0,0 +1,80 @@
Class ExtMoviePlayer_Manager extends KFGFxMoviePlayer_Manager;
var ExtMenu_Gear EGearMenu;
var KF2GUIController MyGUIController;
event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget)
{
local PlayerController PC;
switch ( WidgetName )
{
case 'gearMenu':
PC = GetPC();
if( PC.PlayerReplicationInfo.bReadyToPlay && PC.WorldInfo.GRI.bMatchHasBegun )
return true;
if (EGearMenu == none)
{
EGearMenu = ExtMenu_Gear(Widget);
EGearMenu.InitializeMenu(self);
}
OnMenuOpen( WidgetPath, EGearMenu );
return true;
default:
return Super.WidgetInitialized(WidgetName,WidgetPath,Widget);
}
}
function LaunchMenus( optional bool bForceSkipLobby )
{
local GFxWidgetBinding WidgetBinding;
local bool bSkippedLobby;
// Add either the in game party or out of game party widget
WidgetBinding.WidgetName = 'partyWidget';
bSkippedLobby = bForceSkipLobby || CheckSkipLobby();
WidgetBinding.WidgetClass = class'ExtWidget_PartyInGame';
ManagerObject.SetBool("backgroundVisible", false);
ManagerObject.SetBool("IISMovieVisible", false);
if(bSkippedLobby)
CurrentBackgroundMovie.Stop();
WidgetBindings.AddItem(WidgetBinding);
// Load the platform-specific graphics options menu
switch( class'KFGameEngine'.static.GetPlatform() )
{
case PLATFORM_PC_DX10:
WidgetBinding.WidgetName = 'optionsGraphicsMenu';
WidgetBinding.WidgetClass = class'KFGFxOptionsMenu_Graphics_DX10';
WidgetBindings.AddItem(WidgetBinding);
break;
default:
WidgetBinding.WidgetName = 'optionsGraphicsMenu';
WidgetBinding.WidgetClass = class'KFGFxOptionsMenu_Graphics';
WidgetBindings.AddItem(WidgetBinding);
}
if (!bSkippedLobby)
{
LoadWidgets(WidgetPaths);
OpenMenu(UI_Start);
AllowCloseMenu();
}
// do this stuff in case CheckSkipLobby failed
if( bForceSkipLobby )
{
bAfterLobby = true;
CloseMenus(true);
}
}
defaultproperties
{
WidgetBindings.Remove((WidgetName="PerksMenu",WidgetClass=class'KFGFxMenu_Perks'))
WidgetBindings.Add((WidgetName="PerksMenu",WidgetClass=class'ExtMenu_Perks'))
WidgetBindings.Remove((WidgetName="gearMenu",WidgetClass=class'KFGFxMenu_Gear'))
WidgetBindings.Add((WidgetName="gearMenu",WidgetClass=class'ExtMenu_Gear'))
WidgetBindings.Remove((WidgetName="traderMenu",WidgetClass=class'KFGFxMenu_Trader'))
WidgetBindings.Add((WidgetName="traderMenu",WidgetClass=class'ExtMenu_Trader'))
}

View File

@ -0,0 +1,56 @@
class ExtPawn_Customization extends KFPawn_Customization;
simulated function KFCharacterInfoBase GetCharacterInfo()
{
if( ExtPlayerReplicationInfo(PlayerReplicationInfo)!=None )
return ExtPlayerReplicationInfo(PlayerReplicationInfo).GetSelectedArch();
return Super.GetCharacterInfo();
}
simulated function SetCharacterArch( KFCharacterInfoBase Info, optional bool bForce )
{
local KFPlayerReplicationInfo KFPRI;
KFPRI = KFPlayerReplicationInfo( PlayerReplicationInfo );
if (Info != CharacterArch || bForce)
{
// Set Family Info
CharacterArch = Info;
CharacterArch.SetCharacterFromArch( self, KFPRI );
class'ExtCharacterInfo'.Static.SetCharacterMeshFromArch( KFCharacterInfo_Human(CharacterArch), self, KFPRI );
class'ExtCharacterInfo'.Static.SetFirstPersonArmsFromArch( KFCharacterInfo_Human(CharacterArch), self, KFPRI );
SetCharacterAnimationInfo();
// Sounds
SoundGroupArch = Info.SoundGroupArch;
if (WorldInfo.NetMode != NM_DedicatedServer)
{
// refresh weapon attachment (attachment bone may have changed)
if (WeaponAttachmentTemplate != None)
{
WeaponAttachmentChanged(true);
}
}
}
if( CharacterArch != none )
{
if( CharacterArch.VoiceGroupArchName != "" )
VoiceGroupArch = class<KFPawnVoiceGroup>(class'ExtCharacterInfo'.Static.SafeLoadObject(CharacterArch.VoiceGroupArchName, class'Class'));
}
}
function bool Died(Controller Killer, class<DamageType> DamageType, vector HitLocation)
{
// Destroy this pawn if player leaves.
Destroy();
return true;
}
defaultproperties
{
bCollideActors=false
bBlockActors=false
}

View File

@ -0,0 +1,645 @@
/*
Extended Perk Manager
Written by Marco
*/
Class ExtPerkManager extends KFPerk;
enum EReplicateState
{
REP_CustomCharacters,
REP_CustomInventory,
REP_PerkClasses,
REP_Done
};
const CUR_SaveVersion=2;
var int UserDataVersion;
var transient float LastNapalmTime;
// Server -> Client rep status
var byte RepState;
var int RepIndex;
var array<Ext_PerkBase> UserPerks;
var Ext_PerkBase CurrentPerk;
var int ExpUpStatus[2];
var string StrPerkName;
var ExtPlayerReplicationInfo PRIOwner;
var Controller PlayerOwner;
// Stats
var int TotalEXP,TotalKills,TotalPlayTime;
var bool bStatsDirty,bServerReady,bUserStatsBroken,bCurrentlyHealing;
replication
{
// Things the server should send to the client.
if ( bNetDirty )
CurrentPerk;
}
final function SetGrenadeCap( byte AddedCap )
{
MaxGrenadeCount = Default.MaxGrenadeCount + AddedCap;
if( RepState==REP_Done )
ClientSetGrenadeCap(MaxGrenadeCount);
}
simulated reliable client function ClientSetGrenadeCap( byte NewCap )
{
MaxGrenadeCount = NewCap;
}
function bool ApplyPerkClass( class<Ext_PerkBase> P )
{
local int i;
for( i=0; i<UserPerks.Length; ++i )
if( UserPerks[i].Class==P )
{
ApplyPerk(UserPerks[i]);
return true;
}
return false;
}
function bool ApplyPerkName( string S )
{
local int i;
for( i=0; i<UserPerks.Length; ++i )
if( string(UserPerks[i].Class.Name)~=S )
{
ApplyPerk(UserPerks[i]);
return true;
}
return false;
}
function ApplyPerk( Ext_PerkBase P )
{
if( P==None )
return;
if( CurrentPerk!=None )
CurrentPerk.DeactivateTraits();
bStatsDirty = true;
CurrentPerk = P;
if( PRIOwner!=None )
{
PRIOwner.ECurrentPerk = P.Class;
P.UpdatePRILevel();
}
if( CurrentPerk!=None )
CurrentPerk.ActivateTraits();
}
simulated final function Ext_PerkBase FindPerk( class<Ext_PerkBase> P )
{
local int i;
for( i=0; i<UserPerks.Length; ++i )
if( UserPerks[i].Class==P )
return UserPerks[i];
return None;
}
simulated function PostBeginPlay()
{
SetTimer(0.01,false,'InitPerks');
if( WorldInfo.NetMode!=NM_Client )
SetTimer(1,true,'CheckPlayTime');
}
simulated function InitPerks()
{
local Ext_PerkBase P;
if( WorldInfo.NetMode==NM_Client )
{
foreach DynamicActors(class'Ext_PerkBase',P)
if( P.PerkManager!=Self )
RegisterPerk(P);
}
else if( PRIOwner!=PlayerOwner.PlayerReplicationInfo ) // See if was assigned an inactive PRI.
{
PRIOwner = ExtPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo);
if( PRIOwner!=None )
{
if( CurrentPerk!=None )
{
PRIOwner.ECurrentPerk = CurrentPerk.Class;
CurrentPerk.UpdatePRILevel();
}
PRIOwner.RepKills = TotalKills;
PRIOwner.RepEXP = TotalEXP;
PRIOwner.SetInitPlayTime(TotalPlayTime);
PRIOwner.PerkManager = Self;
}
}
}
function CheckPlayTime()
{
++TotalPlayTime; // Stats.
}
function ServerInitPerks()
{
local int i;
for( i=0; i<UserPerks.Length; ++i )
UserPerks[i].SetInitialLevel();
bServerReady = true;
CurrentPerk = None;
if( StrPerkName!="" )
ApplyPerkName(StrPerkName);
if( CurrentPerk==None )
ApplyPerk(UserPerks[Rand(UserPerks.Length)]);
}
simulated function RegisterPerk( Ext_PerkBase P )
{
UserPerks[UserPerks.Length] = P;
P.PerkManager = Self;
}
simulated function UnregisterPerk( Ext_PerkBase P )
{
UserPerks.RemoveItem(P);
P.PerkManager = None;
}
function Destroyed()
{
local int i;
for( i=(UserPerks.Length-1); i>=0; --i )
{
UserPerks[i].PerkManager = None;
UserPerks[i].Destroy();
}
}
function EarnedEXP( int EXP, optional byte Mode )
{
if( CurrentPerk!=None )
{
// Limit how much EXP we got for healing and welding.
switch( Mode )
{
case 1:
ExpUpStatus[0]+=EXP;
EXP = ExpUpStatus[0]/CurrentPerk.WeldExpUpNum;
if( EXP>0 )
ExpUpStatus[0]-=(EXP*CurrentPerk.WeldExpUpNum);
break;
case 2:
ExpUpStatus[1]+=EXP;
EXP = ExpUpStatus[1]/CurrentPerk.HealExpUpNum;
if( EXP>0 )
ExpUpStatus[1]-=(EXP*CurrentPerk.HealExpUpNum);
break;
}
if( EXP>0 && CurrentPerk.EarnedEXP(EXP) )
{
TotalEXP+=EXP;
PRIOwner.RepEXP+=EXP;
bStatsDirty = true;
}
}
}
// XML stat writing
function OutputXML( ExtStatWriter Data )
{
local string S;
local int i;
Data.StartIntendent("user","ver",string(CUR_SaveVersion));
Data.WriteValue("id64",OnlineSubsystemSteamworks(class'GameEngine'.Static.GetOnlineSubsystem()).UniqueNetIdToInt64(PRIOwner.UniqueId));
Data.WriteValue("name",PRIOwner.PlayerName);
Data.WriteValue("exp",string(TotalEXP));
Data.WriteValue("kills",string(TotalKills));
Data.WriteValue("time",string(TotalPlayTime));
if( ExtPlayerController(Owner)!=None && ExtPlayerController(Owner).PendingPerkClass!=None )
S = string(ExtPlayerController(Owner).PendingPerkClass.Name);
else S = (CurrentPerk!=None ? string(CurrentPerk.Class.Name) : "None");
Data.WriteValue("activeperk",S);
for( i=0; i<UserPerks.Length; ++i )
if( UserPerks[i].HasAnyProgress() )
UserPerks[i].OutputXML(Data);
Data.EndIntendent();
}
// Data saving.
function SaveData( ExtSaveDataBase Data )
{
local int i,o;
Data.FlushData();
Data.SetSaveVersion(++UserDataVersion);
Data.SetArVer(CUR_SaveVersion);
// Write global stats.
Data.SaveInt(TotalEXP,3);
Data.SaveInt(TotalKills,3);
Data.SaveInt(TotalPlayTime,3);
// Write character.
if( PRIOwner!=None )
PRIOwner.SaveCustomCharacter(Data);
else class'ExtPlayerReplicationInfo'.Static.DummySaveChar(Data);
// Write selected perk.
if( ExtPlayerController(Owner)!=None && ExtPlayerController(Owner).PendingPerkClass!=None )
Data.SaveStr(string(ExtPlayerController(Owner).PendingPerkClass.Name));
else Data.SaveStr(CurrentPerk!=None ? string(CurrentPerk.Class.Name) : "");
// Count how many progressed perks we have.
o = 0;
for( i=0; i<UserPerks.Length; ++i )
if( UserPerks[i].HasAnyProgress() )
++o;
// Then write count we have.
Data.SaveInt(o);
// Then perk stats.
for( i=0; i<UserPerks.Length; ++i )
{
if( !UserPerks[i].HasAnyProgress() ) // Skip this perk.
continue;
Data.SaveStr(string(UserPerks[i].Class.Name));
o = Data.TellOffset(); // Mark checkpoint.
Data.SaveInt(0,1); // Reserve space for later.
UserPerks[i].SaveData(Data);
// Now save the skip offset for perk data incase perk gets removed from server.
Data.SeekOffset(o);
Data.SaveInt(Data.TotalSize(),1);
Data.ToEnd();
}
}
// Data loading.
function LoadData( ExtSaveDataBase Data )
{
local int i,j,l,o;
local string S;
Data.ToStart();
UserDataVersion = Data.GetSaveVersion();
// Read global stats.
TotalEXP = Data.ReadInt(3);
TotalKills = Data.ReadInt(3);
TotalPlayTime = Data.ReadInt(3);
// Read character.
if( PRIOwner!=None )
{
PRIOwner.RepKills = TotalKills;
PRIOwner.RepEXP = TotalEXP;
PRIOwner.SetInitPlayTime(TotalPlayTime);
PRIOwner.LoadCustomCharacter(Data);
}
else class'ExtPlayerReplicationInfo'.Static.DummyLoadChar(Data);
// Find selected perk.
CurrentPerk = None;
StrPerkName = Data.ReadStr();
l = Data.ReadInt(); // Perk stats length.
for( i=0; i<l; ++i )
{
S = Data.ReadStr();
o = Data.ReadInt(1); // Read skip offset.
Data.PushEOFLimit(o);
for( j=0; j<UserPerks.Length; ++j )
if( S~=string(UserPerks[j].Class.Name) )
{
UserPerks[j].LoadData(Data);
break;
}
Data.PopEOFLimit();
Data.SeekOffset(o); // Jump to end of this section.
}
bStatsDirty = false;
}
function AddDefaultInventory( KFPawn P )
{
local KFInventoryManager KFIM;
if( P != none && P.InvManager != none )
{
KFIM = KFInventoryManager(P.InvManager);
if( KFIM != none )
{
//Grenades added on spawn
KFIM.GiveInitialGrenadeCount();
}
if( CurrentPerk!=None )
CurrentPerk.AddDefaultInventory(P);
}
}
simulated function PlayerDied()
{
if( CurrentPerk!=None )
CurrentPerk.PlayerDied();
}
function PreNotifyPlayerLeave()
{
if( CurrentPerk!=None )
CurrentPerk.DeactivateTraits();
}
// Start client replication of perks data.
// Call this once the stats has been properly loaded serverside!
function InitiateClientRep()
{
RepState = 0;
RepIndex = 0;
SetTimer(0.01,true,'ReplicateTimer');
}
function ReplicateTimer()
{
switch( RepState )
{
case REP_CustomCharacters: // Replicate custom characters.
if( RepIndex>=PRIOwner.CustomCharList.Length )
{
PRIOwner.AllCharReceived();
RepIndex = 0;
++RepState;
}
else
{
PRIOwner.ReceivedCharacter(RepIndex,PRIOwner.CustomCharList[RepIndex]);
++RepIndex;
}
break;
case REP_CustomInventory: // Replicate custom trader inventory
if( !PRIOwner.OnRepNextItem(PRIOwner,RepIndex) )
{
RepIndex = 0;
++RepState;
}
else ++RepIndex;
break;
case REP_PerkClasses: // Open up all actor channel connections.
if( RepIndex>=UserPerks.Length )
{
RepIndex = 0;
++RepState;
}
else if( UserPerks[RepIndex].bClientAuthorized )
{
if( UserPerks[RepIndex].bPerkNetReady )
++RepIndex;
}
else
{
UserPerks[RepIndex].RemoteRole = ROLE_SimulatedProxy;
if( UserPerks[RepIndex].NextAuthTime<WorldInfo.RealTimeSeconds )
{
UserPerks[RepIndex].NextAuthTime = WorldInfo.RealTimeSeconds+0.5;
UserPerks[RepIndex].ClientAuth();
}
}
break;
default:
if( MaxGrenadeCount!=Default.MaxGrenadeCount )
ClientSetGrenadeCap(MaxGrenadeCount);
ClearTimer('ReplicateTimer');
}
}
function bool CanEarnSmallRadiusKillXP( class<DamageType> DT )
{
return true;
}
simulated function ModifySpeed( out float Speed )
{
if( CurrentPerk!=None )
Speed *= CurrentPerk.Modifiers[0];
}
function ModifyDamageGiven( out int InDamage, optional Actor DamageCauser, optional KFPawn_Monster MyKFPM, optional KFPlayerController DamageInstigator, optional class<KFDamageType> DamageType, optional int HitZoneIdx )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyDamageGiven(InDamage,DamageCauser,MyKFPM,DamageInstigator,DamageType,HitZoneIdx);
}
simulated function ModifyDamageTaken( out int InDamage, optional class<DamageType> DamageType, optional Controller InstigatedBy )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyDamageTaken(InDamage,DamageType,InstigatedBy);
}
simulated function ModifyRecoil( out float CurrentRecoilModifier, KFWeapon KFW )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyRecoil(CurrentRecoilModifier,KFW);
}
simulated function ModifySpread( out float InSpread )
{
if( CurrentPerk!=None )
CurrentPerk.ModifySpread(InSpread);
}
simulated function ModifyRateOfFire( out float InRate, KFWeapon KFW )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyRateOfFire(InRate,KFW);
}
simulated function float GetReloadRateScale(KFWeapon KFW)
{
return (CurrentPerk!=None ? CurrentPerk.GetReloadRateScale(KFW) : 1.f);
}
simulated function bool GetUsingTactialReload( KFWeapon KFW )
{
return (CurrentPerk!=None ? CurrentPerk.GetUsingTactialReload(KFW) : false);
}
function ModifyHealth( out int InHealth )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyHealth(InHealth);
}
function ModifyArmor( out byte MaxArmor )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyArmor(MaxArmor);
}
function float GetKnockdownPowerModifier( optional class<DamageType> DamageType, optional byte BodyPart, optional bool bIsSprinting=false )
{
return (CurrentPerk!=None ? CurrentPerk.GetKnockdownPowerModifier() : 1.f);
}
function float GetStumblePowerModifier( optional KFPawn KFP, optional class<KFDamageType> DamageType, optional out float CooldownModifier, optional byte BodyPart )
{
return (CurrentPerk!=None ? CurrentPerk.GetKnockdownPowerModifier() : 1.f);
}
function float GetStunPowerModifier( optional class<DamageType> DamageType, optional byte HitZoneIdx )
{
return (CurrentPerk!=None ? CurrentPerk.GetStunPowerModifier(DamageType,HitZoneIdx) : 1.f);
}
simulated function ModifyMeleeAttackSpeed( out float InDuration, KFWeapon KFW )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyMeleeAttackSpeed(InDuration);
}
simulated function class<KFProj_Grenade> GetGrenadeClass()
{
return (CurrentPerk!=None ? CurrentPerk.GrenadeClass : GrenadeClass);
}
simulated function ModifyWeldingRate( out float FastenRate, out float UnfastenRate )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyWeldingRate(FastenRate,UnfastenRate);
}
simulated function bool HasNightVision()
{
return (CurrentPerk!=None ? CurrentPerk.bHasNightVision : false);
}
function bool RepairArmor( Pawn HealTarget )
{
return (CurrentPerk!=None ? CurrentPerk.RepairArmor(HealTarget) : false);
}
function bool ModifyHealAmount( out float HealAmount )
{
return (CurrentPerk!=None ? CurrentPerk.ModifyHealAmount(HealAmount) : false);
}
function bool CanNotBeGrabbed()
{
return (CurrentPerk!=None ? !CurrentPerk.bCanBeGrabbed : false);
}
simulated function ModifyMagSizeAndNumber( KFWeapon KFW, out byte MagazineCapacity, optional array< Class<KFPerk> > WeaponPerkClass, optional bool bSecondary=false, optional name WeaponClassname )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyMagSizeAndNumber(KFW,MagazineCapacity,WeaponPerkClass,bSecondary,WeaponClassname);
}
simulated function ModifySpareAmmoAmount( KFWeapon KFW, out int PrimarySpareAmmo, optional const out STraderItem TraderItem, optional bool bSecondary=false )
{
if( CurrentPerk!=None )
CurrentPerk.ModifySpareAmmoAmount(KFW,PrimarySpareAmmo,TraderItem,bSecondary);
}
simulated function ModifyMaxSpareAmmoAmount( KFWeapon KFW, out int SpareAmmoCapacity, optional const out STraderItem TraderItem, optional bool bSecondary=false )
{
if( CurrentPerk!=None )
CurrentPerk.ModifySpareAmmoAmount(KFW,SpareAmmoCapacity,TraderItem,bSecondary);
}
simulated function bool ShouldMagSizeModifySpareAmmo( KFWeapon KFW, optional Class<KFPerk> WeaponPerkClass )
{
return (CurrentPerk!=None ? CurrentPerk.ShouldMagSizeModifySpareAmmo(KFW,WeaponPerkClass) : false);
}
simulated function ModifyHealerRechargeTime( out float RechargeRate )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyHealerRechargeTime(RechargeRate);
}
simulated function bool CanExplosiveWeld()
{
return (CurrentPerk!=None ? CurrentPerk.bExplosiveWeld : false);
}
simulated function bool IsOnContactActive()
{
return (CurrentPerk!=None ? CurrentPerk.bExplodeOnContact : false);
}
function bool CanSpreadNapalm()
{
if( CurrentPerk!=None && CurrentPerk.bNapalmFire && LastNapalmTime!=WorldInfo.TimeSeconds )
{
LastNapalmTime = WorldInfo.TimeSeconds; // Avoid infinite script recursion in KFPawn_Monster.
return true;
}
return false;
}
simulated function bool IsRangeActive()
{
return MyPRI!=None ? MyPRI.bExtraFireRange : false;
}
simulated function DrawSpecialPerkHUD(Canvas C)
{
if( CurrentPerk!=None )
CurrentPerk.DrawSpecialPerkHUD(C);
}
function PlayerKilled( KFPawn_Monster Victim, class<DamageType> DamageType )
{
if( CurrentPerk!=None )
CurrentPerk.PlayerKilled(Victim,DamageType);
}
function ModifyBloatBileDoT( out float DoTScaler )
{
if( CurrentPerk!=None )
CurrentPerk.ModifyBloatBileDoT(DoTScaler);
}
simulated function bool GetIsUberAmmoActive( KFWeapon KFW )
{
return (CurrentPerk!=None ? CurrentPerk.GetIsUberAmmoActive(KFW) : false);
}
function UpdatePerkHeadShots( ImpactInfo Impact, class<DamageType> DamageType, int NumHit )
{
if( CurrentPerk!=None )
CurrentPerk.UpdatePerkHeadShots(Impact,DamageType,NumHit);
}
function CheckForAirborneAgent( KFPawn HealTarget, class<DamageType> DamType, int HealAmount )
{
if( !bCurrentlyHealing && CurrentPerk!=None )
{
// Using boolean to avoid infinite recursion.
bCurrentlyHealing = true;
CurrentPerk.CheckForAirborneAgent(HealTarget,DamType,HealAmount);
bCurrentlyHealing = false;
}
}
simulated function float GetZedTimeModifier( KFWeapon W )
{
return (CurrentPerk!=None ? CurrentPerk.GetZedTimeModifier(W) : 0.f);
}
// Poison darts
function bool IsAcidicCompoundActive()
{
return (CurrentPerk!=None ? CurrentPerk.bToxicDart : false);
}
function ModifyACDamage( out int InDamage )
{
if( CurrentPerk!=None && CurrentPerk.bToxicDart )
InDamage += CurrentPerk.ToxicDartDamage;
}
// Zombie explosion!
function bool CouldBeZedShrapnel( class<KFDamageType> KFDT )
{
return (CurrentPerk!=None ? (CurrentPerk.bFireExplode && class<KFDT_Fire>(KFDT)!=None) : false);
}
simulated function bool ShouldShrapnel()
{
return (CurrentPerk!=None ? (CurrentPerk.bFireExplode && Rand(3)==0) : false);
}
function GameExplosion GetExplosionTemplate()
{
return class'KFPerk_Firebug'.Default.ExplosionTemplate;
}
// SWAT:
simulated function bool HasHeavyArmor()
{
return (CurrentPerk!=None && CurrentPerk.bHeavyArmor);
}
simulated function float GetIronSightSpeedModifier( KFWeapon KFW )
{
return (CurrentPerk!=None ? CurrentPerk.GetIronSightSpeedModifier(KFW) : 1.f);
}
simulated function float GetCrouchSpeedModifier( KFWeapon KFW )
{
return (CurrentPerk!=None ? CurrentPerk.GetIronSightSpeedModifier(KFW) : 1.f);
}
simulated function bool ShouldKnockDownOnBump()
{
return (CurrentPerk!=None && CurrentPerk.bHasSWATEnforcer);
}
defaultproperties
{
bTickIsDisabled=false
NetPriority=3.5
}

View File

@ -0,0 +1,61 @@
class ExtPerksContainer_Details extends KFGFxPerksContainer_Details;
`define AddWeaponsInfo(InClassDef) if( `InClassDef!=None ) AddWeaponInfo(WeaponNames, WeaponSources, `InClassDef.static.GetItemName(), `InClassDef.static.GetImagePath())
final function ExUpdateDetails( Ext_PerkBase PerkClass )
{
local GFxObject DetailsProvider;
local KFPlayerController KFPC;
local KFGameReplicationInfo KFGRI;
local array<string> WeaponNames;
local array<string> WeaponSources;
local int i;
DetailsProvider = CreateObject( "Object" );
KFPC = KFPlayerController( GetPC() );
if ( KFPC != none)
{
KFGRI = KFGameReplicationInfo(KFPC.WorldInfo.GRI);
DetailsProvider.SetString( "ExperienceMessage", ExperienceString @ PerkClass.CurrentEXP );
if(KFGRI != none)
{
`AddWeaponsInfo(PerkClass.PrimaryWeaponDef);
`AddWeaponsInfo(PerkClass.SecondaryWeaponDef);
`AddWeaponsInfo(PerkClass.KnifeWeaponDef);
`AddWeaponsInfo(PerkClass.GrenadeWeaponDef);
}
for (i = 0; i < WeaponNames.length; i++)
{
DetailsProvider.SetString( "WeaponName" $ i, WeaponNames[i] );
DetailsProvider.SetString( "WeaponImage" $ i, "img://"$WeaponSources[i] );
}
DetailsProvider.SetString( "EXPAction1", "Kill zombies" );
//DetailsProvider.SetString( "EXPAction2", PerkClass.default.EXPAction2 );
SetObject( "detailsData", DetailsProvider );
}
}
final function ExUpdatePassives( Ext_PerkBase PerkClass )
{
local GFxObject PassivesProvider;
local GFxObject PassiveObject;
local int i;
PassivesProvider = CreateArray();
for( i=0; i<PerkClass.PerkStats.Length; ++i )
{
PassiveObject = CreateObject( "Object" );
PassiveObject.SetString( "PassiveTitle", PerkClass.GetStatUIStr(i) );
PassiveObject.SetString( "PerkBonusModifier", "");
PassiveObject.SetString( "PerkBonusAmount", "" );
PassivesProvider.SetElementObject( i, PassiveObject );
}
SetObject( "passivesData", PassivesProvider );
}

View File

@ -0,0 +1,19 @@
class ExtPerksContainer_Header extends KFGFxPerksContainer_Header;
final function ExUpdatePerkHeader( Ext_PerkBase PerkClass )
{
local GFxObject PerkDataProvider;
PerkDataProvider = CreateObject( "Object" );
PerkDataProvider.SetString( "perkTitle", PerkClass.PerkName );
PerkDataProvider.SetString( "perkLevel", LevelString@PerkClass.CurrentLevel);
PerkDataProvider.SetString( "iconSource", PerkClass.GetPerkIconPath(PerkClass.CurrentLevel) );
PerkDataProvider.SetString( "prestigeLevel", ""); //not used yet so not point to populating with data
PerkDataProvider.SetString( "xpString", PerkClass.CurrentEXP$"/"$PerkClass.NextLevelEXP );
PerkDataProvider.SetFloat( "xpPercent", PerkClass.GetProgressPercent() );
SetObject( "perkData", PerkDataProvider );
}
defaultproperties
{
}

View File

@ -0,0 +1,48 @@
class ExtPerksContainer_Selection extends KFGFxPerksContainer_Selection;
function UpdatePerkSelection(byte SelectedPerkIndex)
{
local int i;
local GFxObject DataProvider;
local GFxObject TempObj;
local ExtPlayerController KFPC;
local Ext_PerkBase PerkClass;
KFPC = ExtPlayerController( GetPC() );
if ( KFPC!=none && KFPC.ActivePerkManager!=None )
{
DataProvider = CreateArray();
for (i = 0; i < KFPC.ActivePerkManager.UserPerks.Length; i++)
{
PerkClass = KFPC.ActivePerkManager.UserPerks[i];
TempObj = CreateObject( "Object" );
TempObj.SetInt( "PerkLevel", PerkClass.CurrentLevel );
TempObj.SetString( "Title", PerkClass.PerkName );
TempObj.SetString( "iconSource", PerkClass.GetPerkIconPath(PerkClass.CurrentLevel) );
TempObj.SetBool("bTierUnlocked", true);
DataProvider.SetElementObject( i, TempObj );
}
SetObject( "perkData", DataProvider );
SetInt("SelectedIndex", SelectedPerkIndex);
UpdatePendingPerkInfo(SelectedPerkIndex);
}
}
function UpdatePendingPerkInfo(byte SelectedPerkIndex)
{
local ExtPlayerController KFPC;
local Ext_PerkBase PerkClass;
KFPC = ExtPlayerController( GetPC() );
if( KFPC != none )
{
PerkClass = KFPC.ActivePerkManager.UserPerks[SelectedPerkIndex];
SetPendingPerkChanges(PerkClass.PerkName, PerkClass.GetPerkIconPath(PerkClass.CurrentLevel), "Perk changes will be applied when you die.");
}
}
function SavePerk(int PerkID);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
Class ExtPlayerInput extends KFPlayerInput;
var KF2GUIController MyGUIController;
var bool bHandledTravel;
exec function StartCrouch()
{
bDuck = 1;
}
exec function ToggleCrouch()
{
bDuck = (bDuck == 0) ? 1 : 0;
}
simulated exec function IronSights(optional bool bHoldButtonMode)
{
local KFWeapon KFW;
if( Pawn != none )
{
if( KFPawn_Monster(Pawn)!=None )
Pawn.StartFire(1);
else
{
KFW = KFWeapon(Pawn.Weapon);
if ( KFW != None )
KFW.SetIronSights((bHoldButtonMode) ? true : !KFW.bUsingSights);
}
}
}
simulated exec function IronSightsRelease(optional bool bHoldButtonMode)
{
local KFWeapon KFW;
if( Pawn != none )
{
if( KFPawn_Monster(Pawn)!=None )
Pawn.StopFire(1);
else
{
KFW = KFWeapon(Pawn.Weapon);
if ( !KFW.bHasIronSights || bHoldButtonMode )
KFW.SetIronSights(false);
}
}
}
simulated exec function ToggleFlashlight()
{
if( KFPawn_Monster(Pawn)!=None && Pawn.Health>0 )
SetNightVision(!bNightVisionActive);
else Super.ToggleFlashlight();
}
function PreClientTravel( string PendingURL, ETravelType TravelType, bool bIsSeamlessTravel)
{
Super.PreClientTravel(PendingURL,TravelType,bIsSeamlessTravel);
if( !bHandledTravel )
{
bHandledTravel = true;
if( KFExtendedHUD(MyHUD)!=None )
KFExtendedHUD(MyHUD).NotifyLevelChange(true);
}
}
event bool FilterButtonInput(int ControllerId, Name Key, EInputEvent Event, float AmountDepressed, bool bGamepad)
{
if ( MyGfxManager.bAfterLobby && Event==IE_Pressed && (Key == 'Escape' || Key == 'XboxTypeS_Start') )
{
if( MyGUIController==None || MyGUIController.bIsInvalid )
{
MyGUIController = class'KF2GUIController'.Static.GetGUIController(Outer);
if( MyGUIController==None )
{
ExtPlayerController(Outer).CancelConnection();
return false;
}
}
if( MyGUIController.bIsInMenuState )
{
return false;
}
else if( MyGFxManager.bMenusOpen )
{
return MyGFxManager.ToggleMenus();
}
else
{
MyGUIController.OpenMenu(ExtPlayerController(Outer).MidGameMenuClass);
return true;
}
}
return false;
}

View File

@ -0,0 +1,781 @@
Class ExtPlayerReplicationInfo extends KFPlayerReplicationInfo;
struct FCustomCharEntry
{
var bool bLock;
var KFCharacterInfo_Human Char;
var ObjectReferencer Ref;
};
struct FMyCustomChar // Now without constant.
{
var byte CharacterIndex,HeadMeshIndex,HeadSkinIndex,BodyMeshIndex,BodySkinIndex,AttachmentMeshIndices[`MAX_COSMETIC_ATTACHMENTS],AttachmentSkinIndices[`MAX_COSMETIC_ATTACHMENTS];
structdefaultproperties
{
CharacterIndex=255
AttachmentMeshIndices[0]=255
AttachmentMeshIndices[1]=255
AttachmentMeshIndices[2]=255
}
};
// For custom trader inventory.
struct FCustomTraderItem
{
var class<KFWeaponDefinition> WeaponDef;
var class<KFWeapon> WeaponClass;
};
var bool bIsMuted,bInitialPT,bIsDev,bHiddenUser,bClientUseCustom,bClientFirstChar,bClientCharListDone,bClientInitChars;
var int RespawnCounter;
var byte AdminType;
var class<Ext_PerkBase> ECurrentPerk;
var int ECurrentPerkLevel,ECurrentPerkPrestige;
var ExtPerkManager PerkManager;
/* AdminTypes:
0 - Super Admin (server owner)
1 - Admin
2 - Moderator
3 - Trusted member
4 - VIP
*/
var string TaggedPlayerName;
var repnotify string NameTag;
var repnotify byte RepLevelProgress;
var transient color HUDPerkColor;
var byte FixedData;
var int RepPlayTime,RepKills,RepEXP;
// Custom character stuff.
var array<FCustomCharEntry> CustomCharList;
var repnotify FMyCustomChar CustomCharacter;
var transient array<ExtCharDataInfo> SaveDataObjects;
var transient ExtPlayerReplicationInfo LocalOwnerPRI; // Local playercontroller owner PRI
// Custom trader inventory
var KFGFxObject_TraderItems CustomList;
var array<FCustomTraderItem> CustomItems;
// Supplier data:
var transient struct FSupplierData
{
var transient Pawn SuppliedPawn;
var transient float NextSupplyTimer;
} SupplierLimit;
var repnotify class<Ext_TraitSupply> HasSupplier;
replication
{
// Things the server should send to the client.
if ( true )
RespawnCounter,AdminType,ECurrentPerk,ECurrentPerkLevel,ECurrentPerkPrestige,RepKills,RepEXP,RepLevelProgress,bIsDev,NameTag,FixedData,bHiddenUser,CustomCharacter,HasSupplier;
if (bNetInitial || bInitialPT)
RepPlayTime;
}
simulated function PostBeginPlay()
{
local PlayerController PC;
Super.PostBeginPlay();
SetTimer(1,true,'TickPT');
if( WorldInfo.NetMode!=NM_DedicatedServer )
{
HUDPerkColor = PickPerkColor();
PC = GetALocalPlayerController();
if( PC!=None )
LocalOwnerPRI = ExtPlayerReplicationInfo(PC.PlayerReplicationInfo);
}
else LocalOwnerPRI = Self; // Dedicated server can use self PRI.
}
// Resupply traits:
simulated final function bool CanUseSupply( Pawn P )
{
return (SupplierLimit.SuppliedPawn!=P || SupplierLimit.NextSupplyTimer<WorldInfo.TimeSeconds);
}
simulated final function UsedSupply( Pawn P, float NextTime )
{
SupplierLimit.SuppliedPawn = P;
SupplierLimit.NextSupplyTimer = WorldInfo.TimeSeconds+NextTime;
}
simulated function ClientInitialize(Controller C)
{
local ExtPlayerReplicationInfo PRI;
Super.ClientInitialize(C);
if( WorldInfo.NetMode!=NM_DedicatedServer )
{
LocalOwnerPRI = Self;
// Make all other PRI's load character list from local owner PRI.
foreach DynamicActors(class'ExtPlayerReplicationInfo',PRI)
PRI.LocalOwnerPRI = Self;
}
}
simulated function TickPT()
{
++RepPlayTime;
}
simulated event ReplicatedEvent(name VarName)
{
switch( VarName )
{
case 'RepLevelProgress':
HUDPerkColor = PickPerkColor();
break;
case 'CustomCharacter':
CharacterCustomizationChanged();
break;
case 'HasSupplier':
SupplierLimit.SuppliedPawn = None; // Reset if stat was changed.
break;
case 'PlayerName':
case 'NameTag':
UpdateNameTag();
default:
Super.ReplicatedEvent(VarName);
}
}
function SetPlayerName(string S)
{
Super.SetPlayerName(S);
UpdateNameTag();
}
function SetPlayerNameTag( string S )
{
NameTag = S;
UpdateNameTag();
}
function OverrideWith(PlayerReplicationInfo PRI)
{
Super.OverrideWith(PRI);
NameTag = ExtPlayerReplicationInfo(PRI).NameTag;
bAdmin = PRI.bAdmin;
AdminType = ExtPlayerReplicationInfo(PRI).AdminType;
UpdateNameTag();
}
simulated final function UpdateNameTag()
{
if( NameTag!="" )
TaggedPlayerName = "["$NameTag$"] "$PlayerName;
else TaggedPlayerName = PlayerName;
}
final function SetLevelProgress( int CurLevel, int CurPrest, int MinLevel, int MaxLevel )
{
local float V;
ECurrentPerkLevel = CurLevel;
ECurrentPerkPrestige = CurPrest;
V = FClamp((float(CurLevel-MinLevel) / float(MaxLevel-MinLevel))*255.f,0,255);
RepLevelProgress = V;
bForceNetUpdate = true;
if( WorldInfo.NetMode!=NM_DedicatedServer )
HUDPerkColor = PickPerkColor();
}
simulated final function string GetPerkLevelStr()
{
return (ECurrentPerkPrestige>0 ? (string(ECurrentPerkPrestige)$"-"$string(ECurrentPerkLevel)) : string(ECurrentPerkLevel));
}
simulated final function color PickPerkColor()
{
local float P;
local byte i;
if( RepLevelProgress==0 )
return MakeColor(255,255,255,255);
P = float(RepLevelProgress) / 255.f;
if( P<0.25f ) // White - Blue
{
i = 255 - (P*1020.f);
return MakeColor(i,i,255,255);
}
if( P<0.5f ) // Blue - Green
{
i = ((P-0.25f)*1020.f);
return MakeColor(0,i,255-i,255);
}
if( P<0.75f ) // Green - Red
{
i = ((P-0.5f)*1020.f);
return MakeColor(i,255-i,0,255);
}
// Red - Yellow
i = ((P-0.75f)*1020.f);
return MakeColor(255,i,0,255);
}
function SetInitPlayTime( int T )
{
bInitialPT = true;
bForceNetUpdate = true;
RepPlayTime = T;
SetTimer(5,false,'UnsetPT');
}
function UnsetPT()
{
bInitialPT = false;
}
Delegate bool OnRepNextItem( ExtPlayerReplicationInfo PRI, int RepIndex )
{
return false;
}
simulated reliable client function ClientAddTraderItem( int Index, FCustomTraderItem Item )
{
// Make sure to not execute on server.
if( WorldInfo.NetMode!=NM_Client && (PlayerController(Owner)==None || LocalPlayer(PlayerController(Owner).Player)==None) )
return;
if( CustomList==None )
{
CustomList = CreateNewList();
RecheckGRI();
}
CustomItems.AddItem(Item);
SetWeaponInfo(false,Index,Item,CustomList);
}
simulated static final function KFGFxObject_TraderItems CreateNewList()
{
local KFGFxObject_TraderItems L,B;
B = class'KFGameReplicationInfo'.Default.TraderItems;
L = new(B) class'KFGFxObject_TraderItems'; // Make clone of list.
L.SaleItems = B.SaleItems;
L.ArmorPrice = B.ArmorPrice;
L.GrenadePrice = B.GrenadePrice;
return L;
}
simulated static final function SetWeaponInfo( bool bDedicated, int Index, FCustomTraderItem Item, KFGFxObject_TraderItems List )
{
local array<STraderItemWeaponStats> S;
if( List.SaleItems.Length<=Index )
List.SaleItems.Length = Index+1;
List.SaleItems[Index].WeaponDef = Item.WeaponDef;
List.SaleItems[Index].ClassName = Item.WeaponClass.Name;
if( class<KFWeap_DualBase>(Item.WeaponClass)!=None && class<KFWeap_DualBase>(Item.WeaponClass).Default.SingleClass!=None )
List.SaleItems[Index].SingleClassName = class<KFWeap_DualBase>(Item.WeaponClass).Default.SingleClass.Name;
else List.SaleItems[Index].SingleClassName = '';
List.SaleItems[Index].DualClassName = Item.WeaponClass.Default.DualClass!=None ? Item.WeaponClass.Default.DualClass.Name : '';
List.SaleItems[Index].AssociatedPerkClasses = Item.WeaponClass.Static.GetAssociatedPerkClasses();
List.SaleItems[Index].MagazineCapacity = Item.WeaponClass.Default.MagazineCapacity[0];
List.SaleItems[Index].InitialSpareMags = Item.WeaponClass.Default.InitialSpareMags[0];
List.SaleItems[Index].MaxSpareAmmo = Item.WeaponClass.Default.SpareAmmoCapacity[0];
List.SaleItems[Index].MaxSecondaryAmmo = Item.WeaponClass.Default.MagazineCapacity[1] * Item.WeaponClass.Default.SpareAmmoCapacity[1];
List.SaleItems[Index].BlocksRequired = Item.WeaponClass.Default.InventorySize;
List.SaleItems[Index].ItemID = Index;
if( !bDedicated )
{
List.SaleItems[Index].SecondaryAmmoImagePath = Item.WeaponClass.Default.SecondaryAmmoTexture!=None ? "img://"$PathName(Item.WeaponClass.Default.SecondaryAmmoTexture) : "";
List.SaleItems[Index].TraderFilter = Item.WeaponClass.Static.GetTraderFilter();
List.SaleItems[Index].InventoryGroup = Item.WeaponClass.Default.InventoryGroup;
List.SaleItems[Index].GroupPriority = Item.WeaponClass.Default.GroupPriority;
Item.WeaponClass.Static.SetTraderWeaponStats(S);
List.SaleItems[Index].WeaponStats = S;
}
}
simulated function RecheckGRI()
{
local ExtPlayerController PC;
if( KFGameReplicationInfo(WorldInfo.GRI)==None )
SetTimer(0.1,false,'RecheckGRI');
else
{
KFGameReplicationInfo(WorldInfo.GRI).TraderItems = CustomList;
foreach LocalPlayerControllers(class'ExtPlayerController',PC)
if( PC.PurchaseHelper!=None )
PC.PurchaseHelper.TraderItems = CustomList;
}
}
simulated final function bool ShowAdminName()
{
return (bAdmin || AdminType<255);
}
simulated function string GetAdminName()
{
switch( AdminType )
{
case 0:
return "Super Admin";
case 1:
case 255:
return "Admin";
case 2:
return "Mod";
case 3:
return "Trusted Member";
case 4:
return "VIP";
}
}
simulated function string GetAdminNameAbr()
{
switch( AdminType )
{
case 0:
return "S";
case 1:
case 255:
return "A";
case 2:
return "M";
case 3:
return "T";
case 4:
return "V";
}
}
simulated function string GetAdminColor()
{
switch( AdminType )
{
case 0:
return "FF6600";
case 1:
case 255:
return "40FFFF";
case 2:
return "FF33FF";
case 3:
return "FF0000";
case 4:
return "FFD700";
}
}
simulated function color GetAdminColorC()
{
switch( AdminType )
{
case 0:
return MakeColor(255,102,0,255);
case 1:
case 255:
return MakeColor(64,255,255,255);
case 2:
return MakeColor(255,51,255,255);
case 3:
return MakeColor(255,0,0,255);
case 4:
return MakeColor(255,215,0,255);
}
}
simulated function string GetHumanReadableName()
{
return TaggedPlayerName;
}
function SetFixedData( byte M )
{
OnModeSet(Self,M);
FixedData = FixedData | M;
SetTimer(5,false,'ClearFixed');
}
function ClearFixed()
{
FixedData = 0;
}
simulated final function string GetDesc()
{
local string S;
if( (FixedData & 1)!=0 )
S = "A.";
if( (FixedData & 2)!=0 )
S $= "WF.";
if( (FixedData & 4)!=0 )
S $= "G.";
if( (FixedData & 8)!=0 )
S $= "NW.";
if( (FixedData & 16)!=0 )
S $= "WA.";
return S;
}
delegate OnModeSet( ExtPlayerReplicationInfo PRI, byte Num );
simulated final function bool LoadPlayerCharacter( byte CharIndex, out FMyCustomChar CharInfo )
{
local KFCharacterInfo_Human C;
if( CharIndex>=(CharacterArchetypes.Length+CustomCharList.Length) )
return false;
if( SaveDataObjects.Length<=CharIndex )
SaveDataObjects.Length = CharIndex+1;
if( SaveDataObjects[CharIndex]==None )
{
C = (CharIndex<CharacterArchetypes.Length) ? CharacterArchetypes[CharIndex] : CustomCharList[CharIndex-CharacterArchetypes.Length].Char;
SaveDataObjects[CharIndex] = new(None,PathName(C)) class'ExtCharDataInfo';
}
CharInfo = SaveDataObjects[CharIndex].LoadData();
return true;
}
simulated final function bool SavePlayerCharacter()
{
local KFCharacterInfo_Human C;
if( CustomCharacter.CharacterIndex>=(CharacterArchetypes.Length+CustomCharList.Length) )
return false;
if( SaveDataObjects.Length<=CustomCharacter.CharacterIndex )
SaveDataObjects.Length = CustomCharacter.CharacterIndex+1;
if( SaveDataObjects[CustomCharacter.CharacterIndex]==None )
{
C = (CustomCharacter.CharacterIndex<CharacterArchetypes.Length) ? CharacterArchetypes[CustomCharacter.CharacterIndex] : CustomCharList[CustomCharacter.CharacterIndex-CharacterArchetypes.Length].Char;
SaveDataObjects[CustomCharacter.CharacterIndex] = new(None,PathName(C)) class'ExtCharDataInfo';
}
SaveDataObjects[CustomCharacter.CharacterIndex].SaveData(CustomCharacter);
return true;
}
simulated function ChangeCharacter( byte CharIndex, optional bool bFirstSet )
{
local FMyCustomChar NewChar;
local byte i;
if( CharIndex>=(CharacterArchetypes.Length+CustomCharList.Length) || IsClientCharLocked(CharIndex) )
CharIndex = 0;
if( bFirstSet && RepCustomizationInfo.CharacterIndex==CharIndex )
{
// Copy properties from default character info.
NewChar.HeadMeshIndex = RepCustomizationInfo.HeadMeshIndex;
NewChar.HeadSkinIndex = RepCustomizationInfo.HeadSkinIndex;
NewChar.BodyMeshIndex = RepCustomizationInfo.BodyMeshIndex;
NewChar.BodySkinIndex = RepCustomizationInfo.BodySkinIndex;
for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i )
{
NewChar.AttachmentMeshIndices[i] = RepCustomizationInfo.AttachmentMeshIndices[i];
NewChar.AttachmentSkinIndices[i] = RepCustomizationInfo.AttachmentSkinIndices[i];
}
}
if( LoadPlayerCharacter(CharIndex,NewChar) )
{
NewChar.CharacterIndex = CharIndex;
CustomCharacter = NewChar;
ServerSetCharacterX(NewChar);
if( WorldInfo.NetMode==NM_Client )
CharacterCustomizationChanged();
}
}
simulated function UpdateCustomization( byte Type, byte MeshIndex, byte SkinIndex, optional byte SlotIndex )
{
switch( Type )
{
case CO_Head:
CustomCharacter.HeadMeshIndex = MeshIndex;
CustomCharacter.HeadSkinIndex = SkinIndex;
break;
case CO_Body:
CustomCharacter.BodyMeshIndex = MeshIndex;
CustomCharacter.BodySkinIndex = SkinIndex;
break;
case CO_Attachment:
CustomCharacter.AttachmentMeshIndices[SlotIndex] = MeshIndex;
CustomCharacter.AttachmentSkinIndices[SlotIndex] = SkinIndex;
break;
}
SavePlayerCharacter();
ServerSetCharacterX(CustomCharacter);
if( WorldInfo.NetMode==NM_Client )
CharacterCustomizationChanged();
}
simulated final function RemoveAttachments()
{
local byte i;
for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i )
{
CustomCharacter.AttachmentMeshIndices[i] = `CLEARED_ATTACHMENT_INDEX;
CustomCharacter.AttachmentSkinIndices[i] = 0;
}
SavePlayerCharacter();
ServerSetCharacterX(CustomCharacter);
if( WorldInfo.NetMode==NM_Client )
CharacterCustomizationChanged();
}
simulated function ClearCharacterAttachment(int AttachmentIndex)
{
if( UsesCustomChar() )
{
CustomCharacter.AttachmentMeshIndices[AttachmentIndex] = `CLEARED_ATTACHMENT_INDEX;
CustomCharacter.AttachmentSkinIndices[AttachmentIndex] = 0;
}
else Super.ClearCharacterAttachment(AttachmentIndex);
}
reliable server final function ServerSetCharacterX( FMyCustomChar NewMeshInfo )
{
if( NewMeshInfo.CharacterIndex>=(CharacterArchetypes.Length+CustomCharList.Length) || IsClientCharLocked(NewMeshInfo.CharacterIndex) )
return;
CustomCharacter = NewMeshInfo;
if ( Role == Role_Authority )
{
CharacterCustomizationChanged();
}
}
simulated final function bool IsClientCharLocked( byte Index )
{
if( Index<CharacterArchetypes.Length )
return false;
Index-=CharacterArchetypes.Length;
return (Index<CustomCharList.Length && CustomCharList[Index].bLock && !ShowAdminName());
}
simulated reliable client function ReceivedCharacter( byte Index, FCustomCharEntry C )
{
if( WorldInfo.NetMode==NM_DedicatedServer )
return;
if( CustomCharList.Length<=Index )
CustomCharList.Length = Index+1;
CustomCharList[Index] = C;
}
simulated reliable client function AllCharReceived()
{
if( WorldInfo.NetMode==NM_DedicatedServer )
return;
if( !bClientInitChars )
{
OnCharListDone();
NotifyCharListDone();
bClientInitChars = true;
}
}
simulated final function NotifyCharListDone()
{
local KFPawn_Human KFP;
local KFCharacterInfo_Human NewCharArch;
local ExtPlayerReplicationInfo EPRI;
foreach WorldInfo.AllPawns(class'KFPawn_Human', KFP)
{
EPRI = ExtPlayerReplicationInfo(KFP.PlayerReplicationInfo);
if( EPRI!=None )
{
NewCharArch = EPRI.GetSelectedArch();
if( NewCharArch != KFP.CharacterArch )
{
// selected a new character
KFP.SetCharacterArch( NewCharArch );
}
else if( WorldInfo.NetMode != NM_DedicatedServer )
{
// refresh cosmetics only
class'ExtCharacterInfo'.Static.SetCharacterMeshFromArch( NewCharArch, KFP, EPRI );
}
}
}
}
simulated delegate OnCharListDone();
// Player has a server specific setting for a character selected.
simulated final function bool UsesCustomChar()
{
if( LocalOwnerPRI==None )
return false; // Not yet init on client.
return CustomCharacter.CharacterIndex<(LocalOwnerPRI.CustomCharList.Length+CharacterArchetypes.Length);
}
// Client uses a server specific custom character.
simulated final function bool ReallyUsingCustomChar()
{
if( !UsesCustomChar() )
return false;
return (CustomCharacter.CharacterIndex>=CharacterArchetypes.Length);
}
simulated final function KFCharacterInfo_Human GetSelectedArch()
{
if( UsesCustomChar() )
return (CustomCharacter.CharacterIndex<CharacterArchetypes.Length) ? CharacterArchetypes[CustomCharacter.CharacterIndex] : LocalOwnerPRI.CustomCharList[CustomCharacter.CharacterIndex-CharacterArchetypes.Length].Char;
return CharacterArchetypes[RepCustomizationInfo.CharacterIndex];
}
simulated event CharacterCustomizationChanged()
{
local KFPawn_Human KFP;
local KFCharacterInfo_Human NewCharArch;
foreach WorldInfo.AllPawns(class'KFPawn_Human', KFP)
{
if( KFP.PlayerReplicationInfo == self || (KFP.DrivenVehicle != None && KFP.DrivenVehicle.PlayerReplicationInfo == self) )
{
NewCharArch = GetSelectedArch();
if( NewCharArch != KFP.CharacterArch )
{
// selected a new character
KFP.SetCharacterArch( NewCharArch );
}
else if( WorldInfo.NetMode != NM_DedicatedServer )
{
// refresh cosmetics only
class'ExtCharacterInfo'.Static.SetCharacterMeshFromArch( NewCharArch, KFP, self );
}
}
}
}
// Save/Load custom character information.
final function SaveCustomCharacter( ExtSaveDataBase Data )
{
local byte i,c;
local string S;
// Write the name of custom character.
if( UsesCustomChar() )
S = string(GetSelectedArch().Name);
Data.SaveStr(S);
if( S=="" )
return;
// Write selected accessories.
Data.SaveInt(CustomCharacter.HeadMeshIndex);
Data.SaveInt(CustomCharacter.HeadSkinIndex);
Data.SaveInt(CustomCharacter.BodyMeshIndex);
Data.SaveInt(CustomCharacter.BodySkinIndex);
c = 0;
for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i )
{
if( CustomCharacter.AttachmentMeshIndices[i]!=255 )
++c;
}
// Write attachments count.
Data.SaveInt(c);
// Write attachments.
for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i )
{
if( CustomCharacter.AttachmentMeshIndices[i]!=255 )
{
Data.SaveInt(i);
Data.SaveInt(CustomCharacter.AttachmentMeshIndices[i]);
Data.SaveInt(CustomCharacter.AttachmentSkinIndices[i]);
}
}
}
final function LoadCustomCharacter( ExtSaveDataBase Data )
{
local string S;
local byte i,n,j;
if( Data.GetArVer()>=2 )
S = Data.ReadStr();
if( S=="" ) // Stock skin.
return;
for( i=0; i<CharacterArchetypes.Length; ++i )
{
if( string(CharacterArchetypes[i].Name)~=S )
break;
}
if( i==CharacterArchetypes.Length )
{
for( i=0; i<CustomCharList.Length; ++i )
{
if( string(CustomCharList[i].Char.Name)~=S )
break;
}
if( i==CharacterArchetypes.Length )
{
// Character not found = Skip data.
Data.SkipBytes(4);
n = Data.ReadInt();
for( i=0; i<n; ++i )
Data.SkipBytes(3);
return;
}
i+=CharacterArchetypes.Length;
}
CustomCharacter.CharacterIndex = i;
CustomCharacter.HeadMeshIndex = Data.ReadInt();
CustomCharacter.HeadSkinIndex = Data.ReadInt();
CustomCharacter.BodyMeshIndex = Data.ReadInt();
CustomCharacter.BodySkinIndex = Data.ReadInt();
n = Data.ReadInt();
for( i=0; i<n; ++i )
{
j = Min(Data.ReadInt(),`MAX_COSMETIC_ATTACHMENTS-1);
CustomCharacter.AttachmentMeshIndices[j] = Data.ReadInt();
CustomCharacter.AttachmentSkinIndices[j] = Data.ReadInt();
}
bNetDirty = true;
}
// Only used to skip offset (in case of an error).
static final function DummyLoadChar( ExtSaveDataBase Data )
{
local string S;
local byte i,n;
if( Data.GetArVer()>=2 )
S = Data.ReadStr();
if( S=="" ) // Stock skin.
return;
Data.SkipBytes(4);
n = Data.ReadInt();
for( i=0; i<n; ++i )
Data.SkipBytes(3);
}
static final function DummySaveChar( ExtSaveDataBase Data )
{
Data.SaveStr("");
}
// Set admin levels without having to hard-reference to this mod.
event BeginState(Name N)
{
switch( N )
{
case 'Global':
AdminType = 0;
break;
case 'Admin':
AdminType = 1;
break;
case 'Mod':
AdminType = 2;
break;
case 'TMem':
AdminType = 3;
break;
case 'VIP':
AdminType = 4;
break;
case 'User':
AdminType = 255;
break;
}
}
defaultproperties
{
RespawnCounter=-1
AdminType=255
TaggedPlayerName="Player"
}

View File

@ -0,0 +1,95 @@
// Written by Marco.
class ExtProj_CrackerGrenade extends KFProj_FragGrenade
hidedropdown;
var() byte NumCrackers;
simulated function PostBeginPlay()
{
Super.PostBeginPlay();
SetTimer(FuseTime+FRand()*0.25, true, 'ExplodeTimer');
}
simulated function ExplodeTimer()
{
local Actor HitActor;
local vector HitLocation, HitNormal;
if( WorldInfo.NetMode!=NM_Client && InstigatorController==none )
{
Destroy();
return;
}
GetExplodeEffectLocation(HitLocation, HitNormal, HitActor);
if( --NumCrackers==0 )
TriggerExplosion(HitLocation, HitNormal, HitActor);
else SmallExplosion(HitLocation, HitNormal, HitActor);
}
simulated function SmallExplosion(Vector HitLocation, Vector HitNormal, Actor HitActor)
{
local vector NudgedHitLocation, ExplosionDirection;
Velocity = VRand()*(900.f*FRand());
SetPhysics(PHYS_Falling);
if (ExplosionTemplate != None)
{
// using a hitlocation slightly away from the impact point is nice for certain things
NudgedHitLocation = HitLocation + (HitNormal * 32.f);
ExplosionActor = Spawn(ExplosionActorClass, self,, NudgedHitLocation, rotator(HitNormal));
if (ExplosionActor != None)
{
ExplosionActor.RemoteRole = ROLE_None;
ExplosionActor.Instigator = Instigator;
ExplosionActor.InstigatorController = InstigatorController;
PrepareExplosionTemplate();
// If the locations are zero (probably because this exploded in the air) set defaults
if( IsZero(HitLocation) )
HitLocation = Location;
if( IsZero(HitNormal) )
{
HitNormal = vect(0,0,1);
}
// these are needed for the decal tracing later in GameExplosionActor.Explode()
ExplosionTemplate.HitActor = HitActor;
ExplosionTemplate.HitLocation = HitLocation;// NudgedHitLocation
ExplosionTemplate.HitNormal = HitNormal;
// If desired, attach to mover if we hit one
if(bAttachExplosionToHitMover && InterpActor(HitActor) != None)
{
ExplosionActor.Attachee = HitActor;
ExplosionTemplate.bAttachExplosionEmitterToAttachee = TRUE;
ExplosionActor.SetBase(HitActor);
}
// directional?
if (ExplosionTemplate.bDirectionalExplosion)
{
ExplosionDirection = GetExplosionDirection(HitNormal);
//DrawDebugLine(ExplosionActor.Location, ExplosionActor.Location+ExplosionDirection*64, 255, 255, 0, TRUE);
}
// @todo: make this function responsible for setting explosion instance parameters, and take instance parameters
// out of GearExplosion (e.g. Attachee)
PrepareExplosionActor(ExplosionActor);
ExplosionActor.Explode(ExplosionTemplate, ExplosionDirection); // go bewm
}
}
}
simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
{
}
simulated function Explode(vector HitLocation, vector HitNormal);
defaultproperties
{
bCanDisintegrate=false
FuseTime=0.35
NumCrackers=6
bNetTemporary=true
}

View File

@ -0,0 +1,95 @@
// Written by Marco.
class ExtProj_SUPERGrenade extends KFProj_FragGrenade
hidedropdown;
/** On Contact demo skill can turn our grenade into an insta boom device */
var bool bExplodeOnContact;
var class<KFProj_Grenade> ClusterNades;
var() byte NumClusters;
simulated function PostBeginPlay()
{
local KFPerk InstigatorPerk;
local KFPawn InstigatorPawn;
InstigatorPawn = KFPawn(Instigator);
if( InstigatorPawn != none )
{
InstigatorPerk = InstigatorPawn.GetPerk();
if( InstigatorPerk != none )
bExplodeOnContact = InstigatorPerk.IsOnContactActive();
}
Super.PostBeginPlay();
if( Instigator!=None && ExtPlayerReplicationInfo(Instigator.PlayerReplicationInfo)!=None && ExtPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ECurrentPerk!=None )
ClusterNades = ExtPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ECurrentPerk.Default.PerkGrenade;
}
simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
{
if( bExplodeOnContact && Other != Instigator && !Other.bWorldGeometry && Pawn(Other)!=None && Pawn(Other).GetTeamNum() != GetTeamNum() )
{
// For opposing team, make the grenade explode instantly
GetExplodeEffectLocation( HitLocation, HitNormal, Other );
TriggerExplosion( HitLocation, HitNormal, Other );
}
else super.ProcessTouch( Other, HitLocation, HitNormal );
}
simulated function Disintegrate( rotator inDisintegrateEffectRotation ); // Nope!
simulated function TriggerExplosion(Vector HitLocation, Vector HitNormal, Actor HitActor)
{
local byte i;
local KFProj_Grenade P;
if( bHasExploded )
return;
if( InstigatorController==None && WorldInfo.NetMode!=NM_Client ) // Prevent Team-Kill.
{
Destroy();
return;
}
Super.TriggerExplosion(HitLocation,HitNormal,HitActor);
if( WorldInfo.NetMode!=NM_Client )
{
for( i=0; i<NumClusters; ++i )
{
P = Spawn(ClusterNades,,,Location);
if( P!=None )
{
P.InstigatorController = InstigatorController;
P.Init(VRand());
}
}
}
bHasExploded = true;
}
simulated function Destroyed()
{
local Actor HitActor;
local vector HitLocation, HitNormal;
// Final Failsafe check for explosion effect
if( !bHasExploded && WorldInfo.NetMode==NM_Client )
{
GetExplodeEffectLocation(HitLocation, HitNormal, HitActor);
TriggerExplosion(HitLocation, HitNormal, HitActor);
}
}
defaultproperties
{
bCanDisintegrate=false
ClusterNades=class'KFProj_FragGrenade'
DrawScale=2
NumClusters=6
ProjFlightTemplate=ParticleSystem'ZED_Hans_EMIT.FX_Grenade_Explosive_01'
Begin Object Name=ExploTemplate0
Damage=500
DamageRadius=1000
End Object
}

View File

@ -0,0 +1,61 @@
// Written by Marco.
class ExtProj_SUPERMedGrenade extends KFProj_MedicGrenade
hidedropdown;
var() byte NumClusters;
simulated function Disintegrate( rotator inDisintegrateEffectRotation ); // Nope!
simulated function TriggerExplosion(Vector HitLocation, Vector HitNormal, Actor HitActor)
{
local byte i;
local KFProj_MedicGrenade P;
if( bHasExploded )
return;
if( InstigatorController==None && WorldInfo.NetMode!=NM_Client ) // Prevent Team-Kill.
{
Destroy();
return;
}
Super.TriggerExplosion(HitLocation,HitNormal,HitActor);
if( WorldInfo.NetMode!=NM_Client )
{
for( i=0; i<NumClusters; ++i )
{
P = Spawn(class'KFProj_MedicGrenade',,,Location);
if( P!=None )
{
P.InstigatorController = InstigatorController;
P.Init(VRand());
}
}
}
bHasExploded = true;
}
simulated function Destroyed()
{
local Actor HitActor;
local vector HitLocation, HitNormal;
// Final Failsafe check for explosion effect
if( !bHasExploded && WorldInfo.NetMode==NM_Client )
{
GetExplodeEffectLocation(HitLocation, HitNormal, HitActor);
TriggerExplosion(HitLocation, HitNormal, HitActor);
}
}
defaultproperties
{
bCanDisintegrate=false
DrawScale=2
NumClusters=5
ProjFlightTemplate=ParticleSystem'ZED_Hans_EMIT.FX_Grenade_Explosive_01'
Begin Object Name=ExploTemplate0
Damage=170
DamageRadius=800
End Object
}

View File

@ -0,0 +1,21 @@
// Written by Marco.
class ExtProj_SUPERMolotov extends KFProj_MolotovGrenade;
defaultproperties
{
Speed=2500
TerminalVelocity=3500
TossZ=450
bCanDisintegrate=false
DrawScale=2.5
NumResidualFlames=10
ResidualFlameProjClass=class'ExtProj_SUPERMolotovS'
// explosion
Begin Object Name=ExploTemplate0
Damage=750
DamageRadius=500
End Object
}

View File

@ -0,0 +1,12 @@
class ExtProj_SUPERMolotovS extends KFProj_MolotovSplash;
defaultproperties
{
DrawScale=2
// explosion
Begin Object Class=KFGameExplosion Name=ExploTemplate0
Damage=40
DamageRadius=200
End Object
}

View File

@ -0,0 +1,9 @@
class ExtSM_Siren_Scream extends KFSM_Siren_Scream;
DefaultProperties
{
// explosion
Begin Object Name=ExploTemplate0
ActorClassToIgnoreForDamage=class'KFPawn_ZedSirenX'
End Object
}

View File

@ -0,0 +1,42 @@
// Serialization system in UnrealScript, written by Marco.
Interface ExtSaveDataBase;
// File accessor helpers.
// MaxVal for integers are as follow (the lower number you use, the less bits will be reserved):
/* 0: 0-255
1: 0-65535
2: 0-16777215
3: -2147483647 - 2147483647
*/
function SaveInt( int Value, optional byte MaxVal );
function int ReadInt( optional byte MaxVal );
function SaveStr( string S );
function string ReadStr();
// File offset management.
function int TellOffset();
function SeekOffset( int Offset );
function int TotalSize();
function ToEnd();
function ToStart();
function bool AtEnd();
function SkipBytes( int Count );
// Wipe out any saved data.
function FlushData();
// Get file contents in a byte array line.
function GetData( out array<byte> Res );
function SetData( out array<byte> S );
// Archive version (to allow modder to make upgraded stat binarily compatible)
function int GetArVer();
function SetArVer( int Ver );
// Push/Pop file limitators (to prevent it from reading EoF in sub sections).
function PushEOFLimit( int EndOffset );
function PopEOFLimit();
// Get most recent save version for this user.
function int GetSaveVersion();
function SetSaveVersion( int Num );

View File

@ -0,0 +1,157 @@
// Helper actor to find all possible spawnpoints for humans on the map.
Class ExtSpawnPointHelper extends Info
transient;
var transient array<NavigationPoint> PendingList,CheckedList;
var array<Actor> ValidSpawnSpots;
static final function ExtSpawnPointHelper FindHelper( WorldInfo Level )
{
local ExtSpawnPointHelper H;
foreach Level.DynamicActors(class'ExtSpawnPointHelper',H)
return H;
return Level.Spawn(class'ExtSpawnPointHelper');
}
final function Actor PickBestSpawn()
{
local Actor N,BestN;
local KFPawn P;
local float Score,BestScore,Dist;
local KFPawn_Human H;
BestN = None;
BestScore = 0;
foreach ValidSpawnSpots(N)
{
if( Rand(4)==0 )
{
Score = FRand();
foreach WorldInfo.AllPawns(class'KFPawn',P,N.Location,2000.f)
{
if( !P.IsAliveAndWell() )
continue;
Dist = VSize(N.Location-P.Location);
if( FastTrace(P.Location,N.Location) )
Dist*=0.75;
if( P.IsA('KFPawn_Human') )
Score+=(3000.f-Dist)/2000.f;
else Score-=(3500.f-Dist)/2500.f;
}
if( BestN==None || Score>BestScore )
{
BestN = N;
BestScore = Score;
}
}
}
// See if can spawn ontop of other players.
foreach WorldInfo.AllPawns(class'KFPawn_Human',H)
{
if( !H.IsAliveAndWell() || H.Physics==PHYS_Falling || (ExtHumanPawn(H)!=None && ExtHumanPawn(H).bFeigningDeath) )
continue;
Score = FRand();
foreach WorldInfo.AllPawns(class'KFPawn',P,H.Location,2000.f)
{
if( !P.IsAliveAndWell() )
continue;
Dist = VSize(H.Location-P.Location);
if( FastTrace(P.Location,H.Location) )
Dist*=0.75;
if( P.IsA('KFPawn_Human') )
Score+=(3000.f-Dist)/3000.f;
else Score-=(3500.f-Dist)/3500.f;
}
if( BestN==None || Score>BestScore )
{
BestN = H;
BestScore = Score;
}
}
return BestN;
}
function PreBeginPlay()
{
SetTimer(0.2,false,'InitChecker');
}
function InitChecker()
{
local PlayerStart PS,Fallback;
foreach WorldInfo.AllNavigationPoints(class'PlayerStart',PS)
{
Fallback = PS;
if( PS.bEnabled && PS.TeamIndex==0 )
{
CheckSpawn(PS);
if( PendingList.Length!=0 )
break;
}
}
if( PendingList.Length==0 && Fallback!=None )
CheckSpawn(Fallback);
SetTimer(0.001,true,'NextCheck');
}
function NextCheck()
{
local NavigationPoint N;
local byte i;
if( PendingList.Length!=0 )
{
while( ++i<5 && PendingList.Length!=0 )
{
N = PendingList[PendingList.Length-1];
PendingList.Remove(PendingList.Length-1,1);
CheckSpawn(N);
}
}
else
{
ClearTimer('NextCheck');
CheckedList.Length = 0;
}
}
final function CheckSpawn( NavigationPoint N )
{
local vector V;
local ReachSpec R;
local NavigationPoint E;
local KFPawnBlockingVolume P;
V = N.Location;
if( N.MaxPathSize.Radius>30 && N.MaxPathSize.Height>80 && FindSpot(vect(36,36,86),V) && KFDoorMarker(N)==None && PickupFactory(N)==None )
{
//DrawDebugLine(V,V+vect(0,0,50),255,255,255,true);
ValidSpawnSpots.AddItem(N);
}
CheckedList.AddItem(N);
foreach N.PathList(R)
{
E = R.GetEnd();
if( E==None || R.CollisionRadius<30 || R.CollisionHeight<80 || R.Class==Class'ProscribedReachSpec' )
{
//if( E!=None )
// DrawDebugLine(E.Location,N.Location,255,255,0,true);
continue;
}
if( CheckedList.Find(E)!=INDEX_NONE )
continue;
// DO NOT go through any blocking volumes.
V = (N.Location+E.Location) * 0.5;
foreach OverlappingActors(class'KFPawnBlockingVolume',P,VSize(N.Location-V),V)
{
if( P.bBlockPlayers && TraceComponent(V,V,P.CollisionComponent,E.Location,N.Location,vect(36,36,50)) )
break;
}
if( P==None )
{
//DrawDebugLine(E.Location,N.Location,0,255,0,true);
PendingList.AddItem(E);
}
//else DrawDebugLine(E.Location,N.Location,255,0,0,true);
}
}

View File

@ -0,0 +1,7 @@
// Interface class for outputting stats into a file or something.
Interface ExtStatWriter;
function WriteValue( string Key, string Value );
function StartIntendent( string Section, optional string Key, optional string Value );
function EndIntendent();
function ResetFile();

View File

@ -0,0 +1,53 @@
class ExtTraderContainer_Filter extends KFGFxTraderContainer_Filter;
function SetPerkFilterData(byte FilterIndex)
{
local int i;
local GFxObject DataProvider;
local GFxObject FilterObject;
local ExtPlayerController KFPC;
local KFPlayerReplicationInfo KFPRI;
local ExtPerkManager PrM;
SetBool("filterVisibliity", true);
KFPC = ExtPlayerController( GetPC() );
if ( KFPC != none )
{
PrM = KFPC.ActivePerkManager;
KFPRI = KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo);
if ( KFPRI != none && PrM!=None )
{
i = Max(PrM.UserPerks.Find(PrM.CurrentPerk),0);
SetInt("selectedIndex", i);
// Set the title of this filter based on either the perk or the off perk string
if( FilterIndex < PrM.UserPerks.Length )
{
SetString("filterText", PrM.UserPerks[FilterIndex].PerkName);
}
else
{
SetString("filterText", OffPerkString);
}
DataProvider = CreateArray();
for (i = 0; i < PrM.UserPerks.Length; i++)
{
FilterObject = CreateObject( "Object" );
FilterObject.SetString("source", PrM.UserPerks[i].GetPerkIconPath(PrM.UserPerks[i].CurrentLevel));
DataProvider.SetElementObject( i, FilterObject );
}
FilterObject = CreateObject( "Object" );
FilterObject.SetString("source", "img://"$class'KFGFxObject_TraderItems'.default.OffPerkIconPath);
DataProvider.SetElementObject( i, FilterObject );
SetObject( "filterSource", DataProvider );
}
}
}
defaultproperties
{
}

View File

@ -0,0 +1,55 @@
class ExtTraderContainer_PlayerInfo extends KFGFxTraderContainer_PlayerInfo;
function SetPerkInfo()
{
local Ext_PerkBase CurrentPerk;
local ExtPlayerController KFPC;
local float V;
KFPC = ExtPlayerController(GetPC());
if( KFPC!=none && KFPC.ActivePerkManager!=None && KFPC.ActivePerkManager.CurrentPerk!=None )
{
CurrentPerk = KFPC.ActivePerkManager.CurrentPerk;
SetString("perkName", CurrentPerk.PerkName);
SetString("perkIconPath", CurrentPerk.GetPerkIconPath(CurrentPerk.CurrentLevel));
SetInt("perkLevel", CurrentPerk.CurrentLevel);
V = CurrentPerk.GetProgressPercent()*100.f;
SetInt("xpBarValue", int(V));
}
}
function SetPerkList()
{
local GFxObject PerkObject;
local GFxObject DataProvider;
local ExtPlayerController KFPC;
local byte i;
local float PerkPercent;
local Ext_PerkBase P;
KFPC = ExtPlayerController(GetPC());
if( KFPC != none && KFPC.ActivePerkManager!=None )
{
DataProvider = CreateArray();
for (i = 0; i < KFPC.ActivePerkManager.UserPerks.Length; i++)
{
P = KFPC.ActivePerkManager.UserPerks[i];
PerkObject = CreateObject( "Object" );
PerkObject.SetString("name", P.PerkName);
PerkObject.SetString("perkIconSource", P.GetPerkIconPath(P.CurrentLevel));
PerkObject.SetInt("level", P.CurrentLevel);
PerkPercent = P.GetProgressPercent()*100.f;
PerkObject.SetInt("perkXP", int(PerkPercent));
DataProvider.SetElementObject(i, PerkObject);
}
SetObject("perkList", DataProvider);
}
}
defaultproperties
{
}

View File

@ -0,0 +1,73 @@
class ExtTraderContainer_Store extends KFGFxTraderContainer_Store;
function RefreshWeaponListByPerk(byte FilterIndex, const out array<STraderItem> ItemList)
{
local int i, SlotIndex;
local GFxObject ItemDataArray; // This array of information is sent to ActionScript to update the Item data
local array<STraderItem> OnPerkWeapons, SecondaryWeapons, OffPerkWeapons;
local class<KFPerk> TargetPerkClass;
local ExtPlayerController EKFPC;
EKFPC = ExtPlayerController(KFPC);
if ( EKFPC!=none && EKFPC.ActivePerkManager!=None)
{
if( FilterIndex<EKFPC.ActivePerkManager.UserPerks.Length )
TargetPerkClass = EKFPC.ActivePerkManager.UserPerks[FilterIndex].BasePerk;
SlotIndex = 0;
ItemDataArray = CreateArray();
for (i = 0; i < ItemList.Length; i++)
{
if ( IsItemFiltered(ItemList[i]) )
{
continue; // Skip this item if it's in our inventory
}
else if ( ItemList[i].AssociatedPerkClasses.length > 0 && ItemList[i].AssociatedPerkClasses[0] != none && TargetPerkClass != class'KFPerk_Survivalist'
&& (TargetPerkClass==None || ItemList[i].AssociatedPerkClasses.Find(TargetPerkClass) == INDEX_NONE ) )
{
continue; // filtered by perk
}
else
{
if(ItemList[i].AssociatedPerkClasses.length > 0)
{
switch (ItemList[i].AssociatedPerkClasses.Find(TargetPerkClass))
{
case 0: //primary perk
OnPerkWeapons.AddItem(ItemList[i]);
break;
case 1: //secondary perk
SecondaryWeapons.AddItem(ItemList[i]);
break;
default: //off perk
OffPerkWeapons.AddItem(ItemList[i]);
break;
}
}
}
}
for (i = 0; i < OnPerkWeapons.length; i++)
{
SetItemInfo(ItemDataArray, OnPerkWeapons[i], SlotIndex);
SlotIndex++;
}
for (i = 0; i < SecondaryWeapons.length; i++)
{
SetItemInfo(ItemDataArray, SecondaryWeapons[i], SlotIndex);
SlotIndex++;
}
for (i = 0; i < OffPerkWeapons.length; i++)
{
SetItemInfo(ItemDataArray, OffPerkWeapons[i], SlotIndex);
SlotIndex++;
}
SetObject("shopData", ItemDataArray);
}
}

View File

@ -0,0 +1,62 @@
// Webadmin playinfo config variables.
// Just an information holder.
Class ExtWebAdmin_UI extends Object
transient;
/* List of PropTypes:
0 = Integer
1 = Boolean
2 = string
3 = multiline text field
*/
struct FWebAdminConfigInfo
{
var byte PropType;
var name PropName;
var string UIName,UIDesc;
var int NumElements;
structdefaultproperties
{
NumElements=1
}
};
struct FPropGroup
{
var string PageName;
var class<Object> ObjClass;
var array<FWebAdminConfigInfo> Configs;
var delegate<OnGetValue> GetValue;
var delegate<OnSetValue> SetValue;
var int Dupes;
};
var array<FPropGroup> ConfigList;
// Value accessors.
Delegate string OnGetValue( name PropName, int ElementIndex );
Delegate OnSetValue( name PropName, int ElementIndex, string Value );
final function Cleanup()
{
ConfigList.Length = 0;
}
final function AddSettingsPage( string PageName, class<Object> Obj, const out array<FWebAdminConfigInfo> Configs, delegate<OnGetValue> GetFunc, delegate<OnSetValue> SetFunc )
{
local int i;
i = ConfigList.Find('PageName',PageName);
if( i>=0 ) // Make sure no dupe pages.
PageName $= "_"$(ConfigList[i].Dupes++);
i = ConfigList.Length;
ConfigList.Length = i+1;
ConfigList[i].PageName = PageName;
ConfigList[i].ObjClass = Obj;
ConfigList[i].Configs = Configs;
ConfigList[i].GetValue = GetFunc;
ConfigList[i].SetValue = SetFunc;
}
final function bool HasConfigFor( class<Object> Obj )
{
return (ConfigList.Find('ObjClass',Obj)>=0);
}

View File

@ -0,0 +1,131 @@
class ExtWidget_BossHealthBar extends KFGFxWidget_BossHealthBar;
var transient array<KFPawn_Monster> BossList;
var transient float NextBossDistTime,LastHP,LastShield;
var transient byte NumBosses;
var transient bool bVisib,bHasInit;
function TickHud(float DeltaTime)
{
if( !KFPC.bHideBossHealthBar && BossList.Length>0 )
{
if( KFPC.WorldInfo.RealTimeSeconds>LastUpdateTime && HasBossesAlive() )
{
LastUpdateTime = KFPC.WorldInfo.RealTimeSeconds + UpdateTickTime;
if( !bVisib )
{
LastHP = -1;
LastShield = -1;
bVisib = true;
SetVisible(true);
}
UpdateBossInfo();
}
}
else if( bHasInit )
{
NumBosses = 0;
bHasInit = false;
BossList.Length = 0;
if( bVisib )
{
bVisib = false;
SetVisible(false);
}
}
}
final function bool HasBossesAlive()
{
local int i;
for( i=(BossList.Length-1); i>=0; --i )
{
if( BossList[i]==None || BossList[i].bDeleteMe || BossList[i].GetTeamNum()==0 )
{
BossList.Remove(i,1);
--NumBosses;
}
else if( !BossList[i].IsAliveAndWell() )
BossList.Remove(i,1);
}
return (BossList.Length>0);
}
function SetBossPawn(KFPawn_Monster NewBossPawn)
{
if( !KFPC.bHideBossHealthBar && NewBossPawn!=None && NewBossPawn.IsAliveAndWell() )
{
bHasInit = true;
++NumBosses;
BossList.AddItem(NewBossPawn);
}
}
final function UpdateBossInfo()
{
local float V;
local KFPawn_Monster B;
if( NextBossDistTime<KFPC.WorldInfo.RealTimeSeconds )
{
NextBossDistTime = KFPC.WorldInfo.RealTimeSeconds + 1.f;
CheckBestBoss();
}
V = (BossPawn!=None ? FClamp(float(BossPawn.Health) / float(BossPawn.HealthMax),0.f,1.f) : 0.f);
if( LastHP!=V )
{
LastHP = V;
SetFloat("currentHealthPercentValue",V);
}
V = 0.f;
if( NumBosses>1 )
{
foreach BossList(B)
V += FClamp(float(B.Health) / float(B.HealthMax),0.f,1.f);
V /= NumBosses;
}
if( LastShield!=V )
{
LastShield = V;
SetFloat("currentShieldPercecntValue",V);
}
}
final function CheckBestBoss()
{
local KFPawn_Monster B,Best;
local vector Pos;
local float Dist,BestDist;
Pos = (KFPC.ViewTarget!=None ? KFPC.ViewTarget.Location : KFPC.Location);
foreach BossList(B)
{
Dist = VSizeSq(Pos-B.Location);
if( Best==None || Dist<BestDist )
{
Best = B;
BestDist = Dist;
}
}
if( Best!=BossPawn )
{
BossPawn = Best;
SetBossName(Best.BossName);
}
}
function OnNamePlateHidden();
function UpdateBossHealth();
function UpdateBossBattlePhase(int BattlePhase);
function UpdateBossShield(float NewShieldPercect);
DefaultProperties
{
}

View File

@ -0,0 +1,87 @@
class ExtWidget_PartyInGame extends KFGFxWidget_PartyInGame;
var class<Ext_PerkBase> PPerkSlots[6];
var byte PPerkLevels[6];
function GFxObject RefreshSlot(int SlotIndex, KFPlayerReplicationInfo KFPRI)
{
local string PlayerName;
local UniqueNetId AdminId;
local bool bIsLeader;
local bool bIsMyPlayer;
local PlayerController PC;
local GFxObject PlayerInfoObject;
local class<Ext_PerkBase> CurrentPerkClass;
local int CurrentPerkLevel;
local ExtPlayerReplicationInfo EPRI;
PlayerInfoObject = CreateObject("Object");
EPRI = ExtPlayerReplicationInfo(KFPRI);
PC = GetPC();
if(OnlineLobby != none)
{
OnlineLobby.GetLobbyAdmin( OnlineLobby.GetCurrentLobbyId(), AdminId);
}
//leader
bIsLeader = (KFPRI.UniqueId == AdminId);
PlayerInfoObject.SetBool("bLeader", bIsLeader);
//my player
bIsMyPlayer = PC.PlayerReplicationInfo.UniqueId == KFPRI.UniqueId;
MemberSlots[SlotIndex].PlayerUID = KFPRI.UniqueId;
MemberSlots[SlotIndex].PRI = KFPRI;
PlayerInfoObject.SetBool("myPlayer", bIsMyPlayer);
// Update this players perk information
CurrentPerkClass = (EPRI!=None ? EPRI.ECurrentPerk : None);
CurrentPerkLevel = (EPRI!=None ? EPRI.ECurrentPerkLevel : 0);
if ( PPerkSlots[SlotIndex] != CurrentPerkClass || PPerkLevels[SlotIndex] != CurrentPerkLevel )
{
PPerkSlots[SlotIndex] = CurrentPerkClass;
PPerkLevels[SlotIndex] = CurrentPerkLevel;
PlayerInfoObject.SetString("perkLevel", string(CurrentPerkLevel) @ CurrentPerkClass.default.PerkName);
PlayerInfoObject.SetString("perkIconPath", CurrentPerkClass.Static.GetPerkIconPath(CurrentPerkLevel));
}
//perk info
if(MemberSlots[SlotIndex].PerkClass != none)
{
PlayerInfoObject.SetString("perkLevel", MemberSlots[SlotIndex].PerkLevel @MemberSlots[SlotIndex].PerkClass.default.PerkName);
PlayerInfoObject.SetString("perkIconPath", "img://"$MemberSlots[SlotIndex].PerkClass.static.GetPerkIconPath());
}
//perk info
if(!bIsMyPlayer)
{
PlayerInfoObject.SetBool("muted", PC.IsPlayerMuted(KFPRI.UniqueId));
}
// E3 build force update of player name
if( class'WorldInfo'.static.IsE3Build() )
{
// Update this slots player name
PlayerName = KFPRI.PlayerName;
}
else
{
PlayerName = KFPRI.PlayerName;
}
PlayerInfoObject.SetString("playerName", PlayerName);
//player icon
if( class'WorldInfo'.static.IsConsoleBuild(CONSOLE_Orbis) )
{
PlayerInfoObject.SetString("profileImageSource", KFPC.GetPS4Avatar(PlayerName));
}
else
{
PlayerInfoObject.SetString("profileImageSource", KFPC.GetSteamAvatar(KFPRI.UniqueId));
}
if(KFGRI != none)
{
PlayerInfoObject.SetBool("ready", KFPRI.bReadyToPlay && !KFGRI.bMatchHasBegun);
}
return PlayerInfoObject;
}

View File

@ -0,0 +1,155 @@
class Ext_AICommandBasePet extends AICommand_Base_Zed;
var transient Pawn OwnerPawn;
var transient float NextSightCheckTime;
final function vector PickPointNearOwner()
{
local byte i;
local vector V,HL,HN,Start;
Start = OwnerPawn.Location;
if( OwnerPawn.Physics==PHYS_Falling )
{
if( Pawn.Trace(HL,HN,OwnerPawn.Location-vect(0,0,5000),OwnerPawn.Location,false,vect(20,20,60))!=None )
Start = HL;
}
while( true )
{
++i;
V.X = FRand()-0.5;
V.Y = FRand()-0.5;
V = Start + Normal2D(V) * (100.f+FRand()*500.f);
if( i<20 && !FastTrace(V,Start) ) // Destination is inside a wall.
continue;
if( i<20 && FastTrace(V-vect(0,0,100),V) ) // Destination is above a pit.
continue;
break;
}
OwnerPawn = None;
return V;
}
final function bool CanSeeOwner()
{
local Pawn P;
NextSightCheckTime = WorldInfo.TimeSeconds+1.f + FRand();
P = Ext_T_MonsterPRI(PlayerReplicationInfo)!=None ? Ext_T_MonsterPRI(PlayerReplicationInfo).OwnerController.Pawn : None;
if( P!=None && !LineOfSightTo(P) )
return false;
return true;
}
state ZedBaseCommand
{
Begin:
if( Pawn.Physics == PHYS_Falling )
{
DisableMeleeRangeEventProbing();
WaitForLanding();
}
EnableMeleeRangeEventProbing();
// Check for any interrupt transitions
CheckInterruptCombatTransitions();
// Select nearest enemy if current enemy is invalid
if( Enemy == none || Enemy.Health <= 0 || !IsValidAttackTarget(KFPawn(Enemy)) )
SelectEnemy();
// Handle special case if I'm supposed to be attacking a door
if( DoorEnemy != none && DoorEnemy.Health > 0 && VSizeSq( DoorEnemy.Location - Pawn.Location ) < (DoorMeleeDistance * DoorMeleeDistance) ) //200UU
{
`AILog( self$" DoorEnemy: "$DoorEnemy$" starting melee attack", 'Command_Base' );
UpdateHistoryString( "[Attacking : "$DoorEnemy$" at "$WorldInfo.TimeSeconds$"]" );
class'AICommand_Attack_Melee'.static.Melee( Outer, DoorEnemy );
}
// See if we are close to our owner
RecheckOwner:
OwnerPawn = Ext_T_MonsterPRI(PlayerReplicationInfo)!=None ? Ext_T_MonsterPRI(PlayerReplicationInfo).OwnerController.Pawn : None;
if( OwnerPawn!=None )
{
if( Enemy!=None && LineOfSightTo(OwnerPawn) && LineOfSightTo(Enemy) ) // We have sight to our owner and can see enemy, go for it!
{
OwnerPawn = None;
bWaitingOnMovementPlugIn = true;
SetEnemyMoveGoal(self, true,,, ShouldAttackWhileMoving() );
NextSightCheckTime = WorldInfo.TimeSeconds+2.f;
while( bWaitingOnMovementPlugIn && bUsePluginsForMovement )
{
if( NextSightCheckTime<WorldInfo.TimeSeconds && !CanSeeOwner() )
{
ClearMovementInfo();
GoTo'RecheckOwner';
}
Sleep(0.03);
}
}
else if( VSizeSq(OwnerPawn.Location-Pawn.Location)>640000.f || !LineOfSightTo(OwnerPawn) ) // 800.f - Need to move closer to our owner.
{
bWaitingOnMovementPlugIn = true;
SetMovePoint(PickPointNearOwner(),OwnerPawn,,300.f);
while( bWaitingOnMovementPlugIn && bUsePluginsForMovement )
{
Sleep(0.03);
}
}
else // Standing next to our owner.
{
OwnerPawn = None;
Sleep(0.2+FRand()*0.5);
}
}
else if( IsValidAttackTarget(KFPawn(Enemy)) )
{
`AILog( "Calling SetEnemyMoveGoal [Dist:"$VSize(Enemy.Location - Pawn.Location)$"] using offset of "$AttackRange$", because IsWithinBasicMeleeRange() returned false ", 'Command_Base' );
bWaitingOnMovementPlugIn = true;
SetEnemyMoveGoal(self, true,,, ShouldAttackWhileMoving() );
while( bWaitingOnMovementPlugIn && bUsePluginsForMovement )
{
Sleep(0.03);
}
`AiLog("Back from waiting for the movement plug in!!!");
if( Enemy == none )
{
Sleep( FRand() + 0.1f );
Goto( 'Begin' );
}
}
else
{
`AILog("Enemy is invalid melee target" @ Enemy, 'Command_Base');
bFailedToMoveToEnemy = true;
}
// Check combat transitions
CheckCombatTransition();
if( bFailedToMoveToEnemy )
{
if( bFailedPathfind )
{
bFailedPathfind = false;
Sleep( 0.f );
}
else
{
Sleep( 0.f );
}
SetEnemy( GetClosestEnemy( Enemy ) );
}
else
{
Sleep(0.f);
}
Goto('Begin');
}
DefaultProperties
{
}

View File

@ -0,0 +1,16 @@
class Ext_AINoTaunt extends KFSM_PlaySingleAnim;
function SpecialMoveStarted(bool bForced, Name PrevMove)
{
KFPOwner.EndSpecialMove();
}
function SpecialMoveEnded(Name PrevMove, Name NextMove)
{
}
DefaultProperties
{
Handle=KFSM_Taunt
bDisableMovement=true
bDisablesWeaponFiring=true
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
Class Ext_PerkBerserker extends Ext_PerkBase;
var float VampRegenRate,ZedTimeMeleeAtkRate;
replication
{
// Things the server should send to the client.
if ( true )
ZedTimeMeleeAtkRate;
}
simulated function ModifyMeleeAttackSpeed( out float InDuration )
{
InDuration *= Modifiers[4];
if( ZedTimeMeleeAtkRate<1.f && WorldInfo.TimeDilation<1.f )
InDuration *= ZedTimeMeleeAtkRate;
}
simulated function ModifyRateOfFire( out float InRate, KFWeapon KFW )
{
if( IsWeaponOnPerk(KFW) )
{
InRate *= Modifiers[4];
if( ZedTimeMeleeAtkRate<1.f && WorldInfo.TimeDilation<1.f )
InRate *= ZedTimeMeleeAtkRate;
}
}
function PlayerKilled( KFPawn_Monster Victim, class<DamageType> DT )
{
if( VampRegenRate>0 && PlayerOwner.Pawn!=None && PlayerOwner.Pawn.Health>0 && class<KFDamageType>(DT)!=None && class<KFDamageType>(DT).Default.ModifierPerkList.Find(BasePerk)>=0 )
PlayerOwner.Pawn.HealDamage( Max(PlayerOwner.Pawn.HealthMax*VampRegenRate,1), PlayerOwner, class'KFDT_Healing', false, false );
}
defaultproperties
{
PerkName="Berserker"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Berserker'
DefTraitList.Add(class'Ext_TraitWPBers')
DefTraitList.Add(class'Ext_TraitUnGrab')
DefTraitList.Add(class'Ext_TraitVampire')
DefTraitList.Add(class'Ext_TraitSpartan')
DefPerkStats(15)=(bHiddenConfig=false) // Poison damage.
BasePerk=class'KFPerk_Berserker'
PrimaryMelee=class'KFWeap_Knife_Berserker'
PrimaryWeapon=class'KFWeap_Blunt_Crovel'
PerkGrenade=class'KFProj_EMPGrenade'
PrimaryWeaponDef=class'KFWeapDef_Crovel'
KnifeWeaponDef=class'KFweapDef_Knife_Berserker'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Berserker'
AutoBuyLoadOutPath=(class'KFWeapDef_Crovel', class'KFWeapDef_Nailgun', class'KFWeapDef_Pulverizer', class'KFWeapDef_Eviscerator')
ZedTimeMeleeAtkRate=1.0
}

View File

@ -0,0 +1,27 @@
Class Ext_PerkCommando extends Ext_PerkBase;
simulated function bool GetUsingTactialReload( KFWeapon KFW )
{
return (IsWeaponOnPerk(KFW) ? Modifiers[5]<0.65 : false);
}
defaultproperties
{
PerkName="Commando"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Commando'
DefTraitList.Add(class'Ext_TraitWPComm')
DefTraitList.Add(class'Ext_TraitUnCloak')
DefTraitList.Add(class'Ext_TraitEnemyHP')
DefTraitList.Add(class'Ext_TraitEliteReload')
BasePerk=class'KFPerk_Commando'
PrimaryMelee=class'KFWeap_Knife_Commando'
PrimaryWeapon=class'KFWeap_AssaultRifle_AR15'
PerkGrenade=class'KFProj_HEGrenade'
PrimaryWeaponDef=class'KFWeapDef_AR15'
KnifeWeaponDef=class'KFweapDef_Knife_Commando'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Commando'
AutoBuyLoadOutPath=(class'KFWeapDef_AR15', class'KFWeapDef_Bullpup', class'KFWeapDef_AK12', class'KFWeapDef_SCAR')
}

View File

@ -0,0 +1,25 @@
Class Ext_PerkDemolition extends Ext_PerkBase;
defaultproperties
{
PerkName="Demolitionist"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Demolition'
DefTraitList.Add(class'Ext_TraitWPDemo')
DefTraitList.Add(class'Ext_TraitBoomWeld')
DefTraitList.Add(class'Ext_TraitContactNade')
DefTraitList.Add(class'Ext_TraitSupplyGren')
BasePerk=class'KFPerk_Demolitionist'
PrimaryMelee=class'KFWeap_Knife_Demolitionist'
PrimaryWeapon=class'KFWeap_GrenadeLauncher_HX25'
PerkGrenade=class'KFProj_DynamiteGrenade'
PrimaryWeaponDef=class'KFWeapDef_HX25'
KnifeWeaponDef=class'KFWeapDef_Knife_Demo'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Demo'
AutoBuyLoadOutPath=(class'KFWeapDef_HX25', class'KFWeapDef_M79', class'KFWeapDef_M16M203', class'KFWeapDef_RPG7')
DefPerkStats(10)=(bHiddenConfig=true) // No support for mag size on demo.
DefPerkStats(13)=(bHiddenConfig=false) // Self damage.
}

View File

@ -0,0 +1,83 @@
Class Ext_PerkFieldMedic extends Ext_PerkBase;
var float RepairArmorRate,AirborneAgentHealRate;
var byte AirborneAgentLevel;
function bool RepairArmor( Pawn HealTarget )
{
local KFPawn_Human KFPH;
if( RepairArmorRate>0 )
{
KFPH = KFPawn_Human(Healtarget);
if( KFPH != none && KFPH.Armor < KFPH.MaxArmor )
{
KFPH.AddArmor( Round( float(KFPH.MaxArmor) * RepairArmorRate ) );
return true;
}
}
return false;
}
function bool ModifyHealAmount( out float HealAmount )
{
HealAmount*=Modifiers[9];
return (RepairArmorRate>0);
}
simulated function ModifyHealerRechargeTime( out float RechargeRate )
{
RechargeRate/=Modifiers[9];
}
function CheckForAirborneAgent( KFPawn HealTarget, class<DamageType> DamType, int HealAmount )
{
if( (AirborneAgentLevel==1 && WorldInfo.TimeDilation<1.f) || AirborneAgentLevel>1 )
GiveMedicAirborneAgentHealth( HealTarget, DamType, HealAmount );
}
function GiveMedicAirborneAgentHealth( KFPawn HealTarget, class<DamageType> DamType, int HealAmount )
{
local KFPawn KFP;
local int RoundedExtraHealAmount;
RoundedExtraHealAmount = FCeil( float(HealAmount) * AirborneAgentHealRate );
foreach WorldInfo.Allpawns(class'KFPawn', KFP, HealTarget.Location, 500.f)
{
if( KFP.IsAliveAndWell() && WorldInfo.GRI.OnSameTeam( HealTarget, KFP ) )
{
if ( HealTarget == KFP )
KFP.HealDamage( RoundedExtraHealAmount, PlayerOwner, DamType );
else KFP.HealDamage( RoundedExtraHealAmount + HealAmount, PlayerOwner, DamType );
}
}
}
defaultproperties
{
PerkName="Field Medic"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Medic'
DefTraitList.Remove(class'Ext_TraitMedicPistol')
DefTraitList.Add(class'Ext_TraitAirborne')
DefTraitList.Add(class'Ext_TraitWPMedic')
DefTraitList.Add(class'Ext_TraitArmorRep')
DefTraitList.Add(class'Ext_TraitToxicDart')
BasePerk=class'KFPerk_FieldMedic'
HealExpUpNum=3
DefPerkStats(0)=(MaxValue=70)
DefPerkStats(9)=(bHiddenConfig=false) // Heal efficiency
DefPerkStats(15)=(bHiddenConfig=false) // Toxic resistance
DefPerkStats(16)=(bHiddenConfig=false) // Sonic resistance
DefPerkStats(17)=(bHiddenConfig=false) // Fire resistance
PrimaryMelee=class'KFWeap_Knife_FieldMedic'
PrimaryWeapon=class'KFWeap_Pistol_Medic'
PerkGrenade=class'KFProj_MedicGrenade'
SuperGrenade=class'ExtProj_SUPERMedGrenade'
PrimaryWeaponDef=class'KFWeapDef_MedicPistol'
KnifeWeaponDef=class'KFWeapDef_Knife_Medic'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Medic'
AutoBuyLoadOutPath=(class'KFWeapDef_MedicPistol', class'KFWeapDef_MedicSMG', class'KFWeapDef_MedicShotgun', class'KFWeapDef_MedicRifle')
}

View File

@ -0,0 +1,26 @@
Class Ext_PerkFirebug extends Ext_PerkBase;
defaultproperties
{
PerkName="Firebug"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Firebug'
DefTraitList.Add(class'Ext_TraitWPFire')
DefTraitList.Add(class'Ext_TraitNapalm')
DefTraitList.Add(class'Ext_TraitFireExplode')
DefTraitList.Add(class'Ext_TraitFireRange')
BasePerk=class'KFPerk_Firebug'
PrimaryMelee=class'KFWeap_Knife_Firebug'
PrimaryWeapon=class'KFWeap_Flame_CaulkBurn'
PerkGrenade=class'KFProj_MolotovGrenade'
SuperGrenade=class'ExtProj_SUPERMolotov'
PrimaryWeaponDef=class'KFWeapDef_CaulkBurn'
KnifeWeaponDef=class'KFWeapDef_Knife_Firebug'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Firebug'
AutoBuyLoadOutPath=(class'KFWeapDef_CaulkBurn', class'KFWeapDef_DragonsBreath', class'KFWeapDef_FlameThrower', class'KFWeapDef_MicrowaveGun')
DefPerkStats(13)=(Progress=3,bHiddenConfig=false) // Self damage.
DefPerkStats(17)=(bHiddenConfig=false) // Fire resistance
}

View File

@ -0,0 +1,43 @@
Class Ext_PerkGunslinger extends Ext_PerkRhythmPerkBase;
var bool bHasUberAmmo,bHasFanfire;
replication
{
// Things the server should send to the client.
if ( true )
bHasUberAmmo,bHasFanfire;
}
simulated function bool GetIsUberAmmoActive( KFWeapon KFW )
{
return bHasUberAmmo && IsWeaponOnPerk(KFW) && WorldInfo.TimeDilation < 1.f;
}
simulated function float GetZedTimeModifier( KFWeapon W )
{
if( bHasFanfire && WorldInfo.TimeDilation<1.f && IsWeaponOnPerk(W) && BasePerk.Default.ZedTimeModifyingStates.Find(W.GetStateName()) != INDEX_NONE )
return 0.9f;
return 0.f;
}
defaultproperties
{
PerkName="Gunslinger"
DefTraitList.Add(class'Ext_TraitWPGuns')
DefTraitList.Add(class'Ext_TraitUberAmmo')
DefTraitList.Add(class'Ext_TraitFanfire')
DefTraitList.Add(class'Ext_TraitRackEmUp')
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Gunslinger'
BasePerk=class'KFPerk_Gunslinger'
PrimaryMelee=class'KFWeap_Knife_Gunslinger'
PrimaryWeapon=class'KFWeap_Revolver_DualRem1858'
PerkGrenade=class'KFProj_NailBombGrenade'
PrimaryWeaponDef=class'KFWeapDef_Remington1858Dual'
KnifeWeaponDef=class'KFWeapDef_Knife_Gunslinger'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Gunslinger'
AutoBuyLoadOutPath=(class'KFWeapDef_Remington1858', class'KFWeapDef_Remington1858Dual', class'KFWeapDef_Colt1911', class'KFWeapDef_Colt1911Dual',class'KFWeapDef_Deagle', class'KFWeapDef_DeagleDual', class'KFWeapDef_SW500', class'KFWeapDef_SW500Dual')
}

View File

@ -0,0 +1,106 @@
Class Ext_PerkRhythmPerkBase extends Ext_PerkBase;
var byte HeadShotComboCount,MaxRhythmCombo,MissComboCount;
var float RhythmComboDmg;
simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCauser, optional KFPawn_Monster MyKFPM, optional KFPlayerController DamageInstigator, optional class<KFDamageType> DamageType, optional int HitZoneIdx )
{
Super.ModifyDamageGiven(InDamage,DamageCauser,MyKFPM,DamageInstigator,DamageType,HitZoneIdx);
if( RhythmComboDmg>0 && BasePerk==None || (DamageType!=None && DamageType.Default.ModifierPerkList.Find(BasePerk)>=0) || IsWeaponOnPerk(KFWeapon(DamageCauser)) )
InDamage *= (1.f+RhythmComboDmg);
}
final function SetMaxRhythm( byte MaxCombo )
{
MaxRhythmCombo = MaxCombo;
}
final function ResetRhythm()
{
MaxRhythmCombo = 0;
HeadShotComboCount = 0;
RhythmComboDmg = 0;
MissComboCount = 0;
HeadShotMessage(0,true,1);
}
final function UpdateDmgScale( bool bUp )
{
if( bUp )
{
MissComboCount = 0;
HeadShotComboCount = Min(HeadShotComboCount+1,255);
HeadShotMessage(HeadShotComboCount,false,MaxRhythmCombo);
}
else if( HeadShotComboCount>0 && ++MissComboCount==3 )
{
--HeadShotComboCount;
HeadShotMessage(HeadShotComboCount,true,MaxRhythmCombo);
MissComboCount = 0;
}
else return;
RhythmComboDmg = FMin(HeadShotComboCount,MaxRhythmCombo)*0.075;
}
function UpdatePerkHeadShots( ImpactInfo Impact, class<DamageType> DamageType, int NumHit )
{
local int HitZoneIdx;
local KFPawn_Monster KFPM;
if( MaxRhythmCombo<=0 )
return;
KFPM = KFPawn_Monster(Impact.HitActor);
if( KFPM==none || KFPM.GetTeamNum()==0 )
{
if( NumHit < 1 && HeadShotComboCount>0 )
UpdateDmgScale(false);
return;
}
HitZoneIdx = KFPM.HitZones.Find('ZoneName', Impact.HitInfo.BoneName);
if( HitZoneIdx == HZI_Head && KFPM.IsAliveAndWell() )
{
if( class<KFDamageType>(DamageType)!=None && class<KFDamageType>(DamageType).Default.ModifierPerkList.Find(BasePerk)>=0 )
UpdateDmgScale(true);
else if( HeadShotComboCount>0 )
UpdateDmgScale(false);
}
else if( NumHit < 1 && HeadShotComboCount>0 )
UpdateDmgScale(false);
}
reliable client function HeadShotMessage( byte HeadShotNum, bool bMissed, byte MaxHits )
{
local AkEvent TempAkEvent;
local KFPlayerController PC;
PC = KFPlayerController(PlayerOwner);
if( PC==none || PC.MyGFxHUD==none )
{
return;
}
PC.MyGFxHUD.RhythmCounterWidget.SetInt("count", HeadShotNum);
PC.MyGFxHUD.RhythmCounterWidget.SetBonusPercentage(float(HeadShotNum) / float(MaxHits));
if( HeadshotNum==0 )
TempAkEvent = AkEvent'WW_UI_PlayerCharacter.Play_R_Method_Reset';
else if( HeadShotNum<MaxHits )
{
if( !bMissed )
{
//PC.ClientSpawnCameraLensEffect(class'KFCameraLensEmit_RackemHeadShot');
TempAkEvent = AkEvent'WW_UI_PlayerCharacter.Play_R_Method_Hit';
}
}
else if( !bMissed )
{
//PC.ClientSpawnCameraLensEffect(class'KFCameraLensEmit_RackemHeadShotPing');
TempAkEvent = AkEvent'WW_UI_PlayerCharacter.Play_R_Method_Top';
HeadshotNum = 6;
}
if( TempAkEvent != none )
PC.PlayRMEffect( TempAkEvent, 'R_Method', HeadshotNum );
}
defaultproperties
{
}

View File

@ -0,0 +1,41 @@
Class Ext_PerkSWAT extends Ext_PerkBase;
var byte RepTacticalMove;
var float MoveSpeedMods[3];
replication
{
// Things the server should send to the client.
if ( true )
RepTacticalMove;
}
simulated function float GetIronSightSpeedModifier( KFWeapon KFW )
{
return ((RepTacticalMove>0 && IsWeaponOnPerk(KFW)) ? MoveSpeedMods[RepTacticalMove-1] : 1.f);
}
defaultproperties
{
PerkName="SWAT"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_SWAT'
DefTraitList.Add(class'Ext_TraitWPSWAT')
DefTraitList.Add(class'Ext_TraitHeavyArmor')
DefTraitList.Add(class'Ext_TraitTacticalMove')
DefTraitList.Add(class'Ext_TraitSWATEnforcer')
BasePerk=class'KFPerk_SWAT'
PrimaryMelee=class'KFWeap_Knife_SWAT'
PrimaryWeapon=class'KFWeap_SMG_MP7'
PerkGrenade=class'KFProj_FlashBangGrenade'
PrimaryWeaponDef=class'KFWeapDef_MP7'
KnifeWeaponDef=class'KFweapDef_Knife_SWAT'
GrenadeWeaponDef=class'KFWeapDef_Grenade_SWAT'
AutoBuyLoadOutPath=(class'KFWeapDef_MP7', class'KFWeapDef_MP5RAS', class'KFWeapDef_P90', class'KFWeapDef_Kriss')
MoveSpeedMods(0)=1.3
MoveSpeedMods(1)=1.5
MoveSpeedMods(2)=2
}

View File

@ -0,0 +1,48 @@
Class Ext_PerkSharpshooter extends Ext_PerkRhythmPerkBase;
var bool bHasDireReload;
var float ZEDTimeStunPower,DireReloadSpeed;
replication
{
// Things the server should send to the client.
if ( true )
bHasDireReload;
}
simulated function float GetReloadRateScale(KFWeapon KFW)
{
if( bHasDireReload && PlayerOwner.Pawn!=None && PlayerOwner.Pawn.Health<40 )
return Super.GetReloadRateScale(KFW)*DireReloadSpeed;
return Super.GetReloadRateScale(KFW);
}
function float GetStunPowerModifier( optional class<DamageType> DamageType, optional byte HitZoneIdx )
{
if( ZEDTimeStunPower>0 && HitZoneIdx==HZI_Head && WorldInfo.TimeDilation<1.f && (class<KFDamageType>(DamageType)!=None && class<KFDamageType>(DamageType).Default.ModifierPerkList.Find(BasePerk)>=0) )
return Super.GetStunPowerModifier(DamageType,HitZoneIdx) + ZEDTimeStunPower;
return Super.GetStunPowerModifier(DamageType,HitZoneIdx);
}
defaultproperties
{
PerkName="Sharpshooter"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Sharpshooter'
DefTraitList.Add(class'Ext_TraitWPSharp')
DefTraitList.Add(class'Ext_TraitRackEmUp')
DefTraitList.Add(class'Ext_TraitRanger')
DefTraitList.Add(class'Ext_TraitDireReload')
DefTraitList.Add(class'Ext_TraitEliteReload')
BasePerk=class'KFPerk_Sharpshooter'
PrimaryMelee=class'KFWeap_Knife_Sharpshooter'
PrimaryWeapon=class'KFWeap_Rifle_Winchester1894'
PerkGrenade=class'KFProj_FreezeGrenade'
PrimaryWeaponDef=class'KFWeapDef_Winchester1894'
KnifeWeaponDef=class'KFWeapDef_Knife_Sharpshooter'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Sharpshooter'
AutoBuyLoadOutPath=(class'KFWeapDef_Winchester1894', class'KFWeapDef_Crossbow', class'KFWeapDef_M14EBR', class'KFWeapDef_RailGun')
DireReloadSpeed=0.25f
}

View File

@ -0,0 +1,24 @@
Class Ext_PerkSupport extends Ext_PerkBase;
defaultproperties
{
PerkName="Support"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Support'
DefTraitList.Add(class'Ext_TraitWPSupp')
DefTraitList.Add(class'Ext_TraitSupply')
DefTraitList(0)=class'Ext_TraitGrenadeSUpg'
BasePerk=class'KFPerk_Support'
WeldExpUpNum=80
DefPerkStats(0)=(MaxValue=20,CostPerValue=2)
DefPerkStats(8)=(bHiddenConfig=false)
PrimaryMelee=class'KFWeap_Knife_Support'
PrimaryWeapon=class'KFWeap_Shotgun_MB500'
PrimaryWeaponDef=class'KFWeapDef_MB500'
KnifeWeaponDef=class'KFWeapDef_Knife_Support'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Support'
AutoBuyLoadOutPath=(class'KFWeapDef_MB500', class'KFWeapDef_DoubleBarrel', class'KFWeapDef_M4', class'KFWeapDef_AA12')
}

View File

@ -0,0 +1,20 @@
Class Ext_PerkSurvivalist extends Ext_PerkBase;
defaultproperties
{
PerkName="Survivalist"
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Survivalist'
DefTraitList.Add(class'Ext_TraitWPSurv')
//DefTraitList.Add(class'Ext_TraitHeavyArmor')
BasePerk=class'KFPerk_Survivalist'
PrimaryMelee=class'KFWeap_Random'
PrimaryWeapon=class'KFWeap_Knife_Support'
PerkGrenade=class'KFProj_HEGrenade'
PrimaryWeaponDef=class'KFWeapDef_Random'
KnifeWeaponDef=class'KFweapDef_Knife_Support'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Commando'
AutoBuyLoadOutPath=(class'KFWeapDef_DragonsBreath', class'KFWeapDef_M16M203', class'KFWeapDef_MedicRifle')
}

View File

@ -0,0 +1,34 @@
// Trait group info.
Class Ext_TGroupBase extends Object
abstract;
var() string GroupInfo;
var() bool bLimitToOne; // Limit to only one trait for this group.
static function string GetUIInfo( Ext_PerkBase Perk )
{
return (Default.bLimitToOne ? Default.GroupInfo$" (MAX 1)" : Default.GroupInfo);
}
static function string GetUIDesc()
{
return Default.GroupInfo$" trait group";
}
// See if group is already using up limitation.
static function bool GroupLimited( Ext_PerkBase Perk, class<Ext_TraitBase> Trait )
{
local int i;
if( Default.bLimitToOne )
{
for( i=0; i<Perk.PerkTraits.Length; ++i )
if( Perk.PerkTraits[i].CurrentLevel>0 && Perk.PerkTraits[i].TraitType!=Trait && Perk.PerkTraits[i].TraitType.Default.TraitGroup==Default.Class )
return true;
}
return false;
}
defaultproperties
{
GroupInfo="Group"
}

View File

@ -0,0 +1,6 @@
class Ext_TGroupMonster extends Ext_TGroupBase;
defaultproperties
{
GroupInfo="Monster"
}

View File

@ -0,0 +1,34 @@
class Ext_TGroupRegen extends Ext_TGroupBase;
static function string GetUIInfo( Ext_PerkBase Perk )
{
return Default.GroupInfo$" (MAX "$GetMaxLimit(Perk)$")";
}
static function string GetUIDesc()
{
return Super.GetUIDesc()$"|To buy additional regen abilities:|-Prestige level 1 + Perk level 100 = MAX 2 traits|-Prestige level 5 + Perk level 150 = MAX 3 traits";
}
static function bool GroupLimited( Ext_PerkBase Perk, class<Ext_TraitBase> Trait )
{
local int i;
local byte n;
n = GetMaxLimit(Perk);
for( i=0; i<Perk.PerkTraits.Length; ++i )
if( Perk.PerkTraits[i].CurrentLevel>0 && Perk.PerkTraits[i].TraitType!=Trait && Perk.PerkTraits[i].TraitType.Default.TraitGroup==Default.Class && --n==0 )
return true;
return false;
}
static final function byte GetMaxLimit( Ext_PerkBase Perk )
{
if( Perk.CurrentPrestige<1 || Perk.CurrentLevel<100 )
return 1;
return ((Perk.CurrentPrestige<5 || Perk.CurrentLevel<150) ? 2 : 3);
}
defaultproperties
{
GroupInfo="Regeneration"
}

View File

@ -0,0 +1,39 @@
Class Ext_T_AmmoRegHelp extends Info
transient;
var Pawn PawnOwner;
var float RegCount;
function PostBeginPlay()
{
PawnOwner = Pawn(Owner);
if( PawnOwner==None )
Destroy();
else SetTimer(29+FRand(),true);
}
function Timer()
{
local KFWeapon W;
local byte i;
if( PawnOwner==None || PawnOwner.Health<=0 || PawnOwner.InvManager==None )
Destroy();
else
{
foreach PawnOwner.InvManager.InventoryActors(class'KFWeapon',W)
{
for( i=0; i<2; ++i )
{
if( W.SpareAmmoCount[i]<W.SpareAmmoCapacity[i] )
{
W.SpareAmmoCount[i] = Min(W.SpareAmmoCount[i]+FMax(float(W.SpareAmmoCapacity[i])*RegCount,1.f),W.SpareAmmoCapacity[i]);
W.bNetDirty = true;
}
}
}
}
}
defaultproperties
{
}

View File

@ -0,0 +1,16 @@
Class Ext_T_ArmorRegHelp extends Ext_T_HealthRegHelp
transient;
function Timer()
{
if( PawnOwner==None || PawnOwner.Health<=0 )
Destroy();
else if( PawnOwner.Armor<PawnOwner.MaxArmor )
{
PawnOwner.Armor = Min(PawnOwner.Armor+RegCount,PawnOwner.MaxArmor);
}
}
defaultproperties
{
}

View File

@ -0,0 +1,55 @@
Class Ext_T_AutoFireHelper extends Info
transient;
var class<KFPerk> AssociatedPerkClass;
var Pawn PawnOwner;
var PlayerController LocalPC;
var bool bNetworkOwner;
replication
{
if ( bNetOwner )
PawnOwner,AssociatedPerkClass;
}
function PostBeginPlay()
{
PawnOwner = Pawn(Owner);
if( PawnOwner==None )
Destroy();
else SetTimer(0.5+FRand()*0.4,true);
}
function Timer()
{
if( PawnOwner==None || PawnOwner.Health<=0 || PawnOwner.InvManager==None )
Destroy();
}
simulated function Tick( float Delta )
{
if( WorldInfo.NetMode==NM_DedicatedServer || PawnOwner==None || PawnOwner.InvManager==None || KFWeapon(PawnOwner.Weapon)==None || KFWeapon(PawnOwner.Weapon).GetWeaponPerkClass(AssociatedPerkClass)!=AssociatedPerkClass )
return;
// Find local playercontroller.
if( LocalPC==None )
{
LocalPC = PlayerController(PawnOwner.Controller);
if( LocalPC==None )
return;
bNetworkOwner = (LocalPlayer(LocalPC.Player)!=None);
}
if( !bNetworkOwner )
return;
// Force always to pending fire.
if( LocalPC.bFire!=0 && !PawnOwner.InvManager.IsPendingFire(None,0) )
PawnOwner.Weapon.StartFire(0);
else if( LocalPC.bAltFire!=0 && !PawnOwner.InvManager.IsPendingFire(None,1) )
PawnOwner.Weapon.StartFire(1);
}
defaultproperties
{
Components.Empty()
RemoteRole=ROLE_SimulatedProxy
bOnlyRelevantToOwner=true
}

View File

@ -0,0 +1,124 @@
Class Ext_T_GhostHelper extends Ext_TraitDataStore;
var KFPawn_Human LastDied;
var float LastDiedTimer,TeleTime;
var vector ResPoint,TeleStartPoint;
var ExtSpawnPointHelper SpawnPointer;
var bool bTeleporting,bIsDelayed;
function bool CanResPlayer( KFPawn_Human Other, byte Level )
{
if( bTeleporting )
{
if( LastDied!=None )
LastDied.Health = 9999;
return true;
}
if( LastDied==Other )
{
if( Level==1 || LastDiedTimer>WorldInfo.TimeSeconds )
return false;
}
else if( Level==1 && Rand(2)==0 )
return false;
LastDied = Other;
bTeleporting = true;
if( SpawnPointer==None )
SpawnPointer = class'ExtSpawnPointHelper'.Static.FindHelper(WorldInfo);
ResPoint = SpawnPointer.PickBestSpawn().Location;
LastDied.FindSpot(vect(36,36,86),ResPoint);
if( VSizeSq(LastDied.Location-ResPoint)<1.f ) // Prevent division by zero errors in future.
ResPoint.Z+=5;
Enable('Tick');
StartResurrect();
return true;
}
final function StartResurrect()
{
TeleStartPoint = LastDied.Location;
LastDied.Health = 9999;
LastDied.LastStartTime = WorldInfo.TimeSeconds;
if( ExtHumanPawn(LastDied)!=None )
{
ExtHumanPawn(LastDied).bCanBecomeRagdoll = false;
if( !ExtHumanPawn(LastDied).CanBeRedeemed() )
{
bIsDelayed = true;
return;
}
}
LastDied.SetCollision(false);
LastDied.bIgnoreForces = true;
LastDied.bAmbientCreature = true;
LastDied.SetPhysics(PHYS_None);
LastDied.bCollideWorld = false;
TeleTime = FClamp(VSize(ResPoint-TeleStartPoint)/900.f,1.f,10.f);
LastDiedTimer = WorldInfo.TimeSeconds+TeleTime;
}
function Tick( float Delta )
{
if( !bTeleporting )
{
Disable('Tick');
return;
}
if( LastDied==None || LastDied.Health<=0 )
{
bTeleporting = false;
return;
}
if( bIsDelayed )
{
bIsDelayed = false;
StartResurrect();
return;
}
Delta = (LastDiedTimer-WorldInfo.TimeSeconds);
if( Delta<=0 )
{
EndGhostTeleport();
return;
}
Delta /= TeleTime;
LastDied.Velocity = Normal(ResPoint-TeleStartPoint)*900.f;
LastDied.SetLocation(TeleStartPoint*Delta+ResPoint*(1.f-Delta));
if( LastDied.Physics!=PHYS_None )
LastDied.SetPhysics(PHYS_None);
}
final function EndGhostTeleport()
{
LastDiedTimer = WorldInfo.TimeSeconds+180.f;
bTeleporting = false;
LastDied.Health = LastDied.HealthMax;
LastDied.SetCollision(true);
LastDied.bIgnoreForces = false;
LastDied.bAmbientCreature = false;
LastDied.bCollideWorld = true;
LastDied.FindSpot(vect(36,36,86),ResPoint);
LastDied.SetLocation(ResPoint);
LastDied.SetPhysics(PHYS_Falling);
LastDied.Velocity = vect(0,0,0);
LastDied.LastStartTime = WorldInfo.TimeSeconds; // For spawn protection, if any.
if( LastDied.IsDoingSpecialMove() ) // Stop any grabbing zeds.
LastDied.EndSpecialMove();
if( ExtHumanPawn(LastDied)!=None )
ExtHumanPawn(LastDied).bCanBecomeRagdoll = true;
}
function Destroyed()
{
if( bTeleporting && LastDied!=None && LastDied.Health>0 )
EndGhostTeleport();
}
defaultproperties
{
}

View File

@ -0,0 +1,26 @@
Class Ext_T_HealthRegHelp extends Info
transient;
var KFPawn_Human PawnOwner;
var byte RegCount;
function PostBeginPlay()
{
PawnOwner = KFPawn_Human(Owner);
if( PawnOwner==None )
Destroy();
else SetTimer(9+FRand(),true);
}
function Timer()
{
if( PawnOwner==None || PawnOwner.Health<=0 )
Destroy();
else if( PawnOwner.Health<PawnOwner.HealthMax )
{
PawnOwner.Health = Min(PawnOwner.Health+RegCount,PawnOwner.HealthMax);
}
}
defaultproperties
{
}

View File

@ -0,0 +1,63 @@
Class Ext_T_MonsterPRI extends PlayerReplicationInfo;
var repnotify class<Pawn> MonsterType;
var repnotify PlayerReplicationInfo OwnerPRI;
var Controller OwnerController;
var string MonsterName;
var int HealthStatus,HealthMax;
var Pawn PawnOwner;
var KFExtendedHUD OwnerHUD;
replication
{
// Things the server should send to the client.
if (bNetDirty)
OwnerPRI,MonsterType,HealthStatus,HealthMax;
}
// Make no efforts with this one.
simulated event PostBeginPlay()
{
if( WorldInfo.NetMode!=NM_Client )
SetTimer(1,true);
}
simulated event Destroyed()
{
if( OwnerHUD!=None )
{
OwnerHUD.MyCurrentPet.RemoveItem(Self);
OwnerHUD = None;
}
if ( WorldInfo.GRI != None )
WorldInfo.GRI.RemovePRI(self);
}
simulated event ReplicatedEvent(name VarName)
{
if( VarName=='OwnerPRI' && OwnerPRI!=None )
NotifyOwner();
else if( VarName=='MonsterType' && MonsterType!=None )
MonsterName = Class'KFExtendedHUD'.Static.GetNameOf(MonsterType);
}
simulated function Timer()
{
if( PawnOwner==None || PawnOwner.Health<=0 )
Destroy();
else if( HealthStatus!=PawnOwner.Health )
HealthStatus = PawnOwner.Health;
}
simulated final function NotifyOwner()
{
local PlayerController PC;
PC = GetALocalPlayerController();
if( PC==None || PC.PlayerReplicationInfo!=OwnerPRI || KFExtendedHUD(PC.MyHUD)==None )
return;
OwnerHUD = KFExtendedHUD(PC.MyHUD);
OwnerHUD.MyCurrentPet.AddItem(Self);
}
defaultproperties
{
bBot=true
MonsterName="Petty"
}

View File

@ -0,0 +1,205 @@
class Ext_T_SupplierInteract extends KFUsablePerkTrigger;
struct FActiveUsers
{
var Pawn Player;
var transient float NextUseTime;
};
var array<FActiveUsers> ActiveUsers;
var repnotify KFPawn_Human PlayerOwner;
var Ext_PerkBase PerkOwner;
var() float ReuseTime;
var bool bGrenades;
replication
{
if( true )
PlayerOwner,bGrenades;
}
simulated event ReplicatedEvent(name VarName)
{
if( VarName=='PlayerOwner' && PlayerOwner!=None )
{
SetLocation(PlayerOwner.Location);
SetBase(PlayerOwner);
}
}
simulated function int GetInteractionIndex( Pawn User )
{
return (bGrenades ? IMT_ReceiveGrenades : InteractionIndex);
}
simulated event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal)
{
local KFPawn_Human KFP;
Super.Touch(Other, OtherComp, HitLocation, HitNormal);
KFP = KFPawn_Human(Other);
if( KFP != none && KFP.Controller != none && KFP != PlayerOwner )
{
KFPlayerController(KFP.Controller).SetPendingInteractionMessage();
}
}
simulated event UnTouch(Actor Other)
{
local KFPawn_Human KFP;
super.UnTouch( Other );
KFP = KFPawn_Human(Other);
if( KFP != none && KFP.Controller != none && KFP != PlayerOwner )
{
KFPlayerController(KFP.Controller).SetPendingInteractionMessage();
}
}
simulated function RecheckUser()
{
local KFPawn_Human Toucher;
// Notify local player owner that this is available again.
foreach TouchingActors(class'KFPawn_Human', Toucher)
{
if( Toucher.IsLocallyControlled() )
Touch(Toucher,None,Location,vect(1,0,0));
}
}
simulated function bool GetCanInteract( Pawn User, optional bool bInteractIfTrue = false)
{
local int i;
local ExtPlayerReplicationInfo PRI;
if( PlayerOwner==None || User==PlayerOwner || KFPawn_Human(User)==None || User.Health<=0 )
return false;
if( WorldInfo.NetMode==NM_Client )
{
PRI = ExtPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo);
if( !User.IsLocallyControlled() || PRI==None || !PRI.CanUseSupply(User) )
return false;
if( bInteractIfTrue )
{
PRI.UsedSupply(User,ReuseTime);
SetTimer(ReuseTime+0.1,false,'RecheckUser');
if( KFPlayerController(User.Controller)!=None )
KFPlayerController(User.Controller).SetPendingInteractionMessage();
}
}
else
{
i = ActiveUsers.Find('Player',User);
if( i>=0 && ActiveUsers[i].NextUseTime>WorldInfo.TimeSeconds )
return false;
if( bInteractIfTrue )
{
if( i==-1 )
{
i = ActiveUsers.Length;
ActiveUsers.Length = i+1;
ActiveUsers[i].Player = User;
SetTimer(10.f,true,'CleanupUsers');
}
ActiveUsers[i].NextUseTime = WorldInfo.TimeSeconds+ReuseTime;
}
}
if( bInteractIfTrue && WorldInfo.NetMode!=NM_Client )
{
GiveAmmunition(KFPawn_Human(User));
}
return true;
}
function CleanupUsers()
{
local int i;
for( i=(ActiveUsers.Length-1); i>=0; --i )
if( ActiveUsers[i].Player==None || ActiveUsers[i].Player.Health<=0 || ActiveUsers[i].NextUseTime<WorldInfo.TimeSeconds )
ActiveUsers.Remove(i,1);
if( ActiveUsers.Length==0 )
ClearTimer('CleanupUsers');
}
final function GiveAmmunition( KFPawn_Human Other )
{
local KFWeapon KFW;
if( PlayerController(PlayerOwner.Controller)!=None )
PlayerController(PlayerOwner.Controller).ReceiveLocalizedMessage( class'KFLocalMessage_Game', (bGrenades ? GMT_GaveGrenadesTo : GMT_GaveAmmoTo), Other.PlayerReplicationInfo );
if( PlayerController(Other.Controller)!=None )
{
PlayerController(Other.Controller).ReceiveLocalizedMessage( class'KFLocalMessage_Game', (bGrenades ? GMT_ReceivedGrenadesFrom : GMT_ReceivedAmmoFrom), PlayerOwner.PlayerReplicationInfo );
if( ExtPlayerController(Other.Controller)!=None )
ExtPlayerController(Other.Controller).ClientUsedAmmo(Self);
}
if( PerkOwner!=None )
PerkOwner.EarnedEXP(25);
if( bGrenades )
{
if( KFInventoryManager(Other.InvManager)!=None )
KFInventoryManager(Other.InvManager).AddGrenades(1);
}
else
{
foreach Other.InvManager.InventoryActors( class'KFWeapon', KFW )
{
if( KFW.DenyPerkResupply() )
continue;
// resupply 1 mag for every 5 initial mags
KFW.AddAmmo( Max( KFW.InitialSpareMags[0] / 3, 1 ) * KFW.MagazineCapacity[0] );
if( KFW.CanRefillSecondaryAmmo() )
{
// resupply 1 mag for every 5 initial mags
KFW.AddSecondaryAmmo( Max( KFW.InitialSpareMags[1] / 3, 1 ) );
}
}
}
}
simulated final function UsedOnClient( Pawn User )
{
local ExtPlayerReplicationInfo PRI;
PRI = ExtPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo);
if( PRI!=None )
PRI.UsedSupply(User,ReuseTime);
SetTimer(ReuseTime+0.1,false,'RecheckUser');
if( WorldInfo.NetMode==NM_Client && KFPlayerController(User.Controller)!=None )
KFPlayerController(User.Controller).SetPendingInteractionMessage();
}
simulated function Destroyed()
{
local KFPawn_Human Toucher;
//notify all touching actors that they are not touching this non existing trigger anymore
foreach TouchingActors(class'KFPawn_Human', Toucher)
{
UnTouch(Toucher);
}
}
DefaultProperties
{
InteractionIndex=IMT_ReceiveAmmo
RemoteRole=ROLE_SimulatedProxy
bSkipActorPropertyReplication=true
bHidden=false
ReuseTime=90
bProjTarget=false
Components.Empty()
Components.Add(CollisionCylinder)
}

View File

@ -0,0 +1,30 @@
Class Ext_T_UnCloakHelper extends Info
transient;
var Pawn PawnOwner;
var float HandleRadius;
function PostBeginPlay()
{
PawnOwner = Pawn(Owner);
if( PawnOwner==None )
Destroy();
else SetTimer(0.5+FRand()*0.1,true);
}
function Timer()
{
local KFPawn_Monster M;
if( PawnOwner==None || PawnOwner.Health<=0 )
Destroy();
else
{
foreach WorldInfo.AllPawns(class'KFPawn_Monster',M,PawnOwner.Location,HandleRadius)
if( M.bCanCloak )
M.CallOutCloaking();
}
}
defaultproperties
{
}

View File

@ -0,0 +1,243 @@
Class Ext_T_ZEDHelper extends Info
transient
DependsOn(Ext_TraitZED_Summon)
config(ServerExt);
var config array<FZEDTypes> ZedTypes; // Dummy hack, not really config but merely just for being able to set class on defaults.
var() float FriendlyScalar;
var Pawn PawnOwner;
var byte CurLevel,RespawnHelperTime,NoLiveCounter;
var KFPawn_Monster LiveHelper;
var class<KFPawn_Monster> PrevMonster;
var float PrevMonsterHP;
var float HPScale,DamageScale;
var int OldKillsValue;
var bool bNeedsKillZed,bIsExtra;
function PostBeginPlay()
{
PawnOwner = Pawn(Owner);
bNeedsKillZed = true;
if( PawnOwner==None )
Destroy();
else
{
OldKillsValue = PawnOwner.PlayerReplicationInfo.Kills;
SetTimer(1+(FRand()*0.1),true);
}
}
function Timer()
{
if( PawnOwner==None || PawnOwner.Health<=0 || PawnOwner.PlayerReplicationInfo==None )
Destroy();
else if( bNeedsKillZed )
{
if( RespawnHelperTime>1 )
--RespawnHelperTime;
if( OldKillsValue==PawnOwner.PlayerReplicationInfo.Kills )
return;
bNeedsKillZed = false;
}
else if( RespawnHelperTime>0 )
{
if( --RespawnHelperTime==0 )
SpawnHelper();
}
else if( LiveHelper==None || LiveHelper.Health<=0 )
{
OldKillsValue = PawnOwner.PlayerReplicationInfo.Kills;
bNeedsKillZed = true;
RespawnHelperTime = 60;
}
else if( !HasLiveZeds() )
{
if( NoLiveCounter==0 )
{
PrevMonster = LiveHelper.Class;
PrevMonsterHP = (float(LiveHelper.Health) / LiveHelper.HealthMax);
LiveHelper.Died(None,class'KFDT_Healing',vect(0,0,0));
RespawnHelperTime = 5;
}
else --NoLiveCounter;
}
else NoLiveCounter = 5;
}
function Destroyed()
{
if( LiveHelper!=None && LiveHelper.Health>0 )
LiveHelper.Died(None,class'DmgType_Suicided',vect(0,0,0));
}
final function bool HasLiveZeds()
{
local KFPawn_Monster M;
if( KFGameReplicationInfo(WorldInfo.GRI).WaveNum>KFGameReplicationInfo(WorldInfo.GRI).WaveMax ) // No pets on possible bonus waves.
return false;
foreach WorldInfo.AllPawns(Class'KFPawn_Monster',M)
if( M.Health>0 && M.GetTeamNum()!=0 )
return true;
return false;
}
final function SpawnHelper()
{
local class<KFPawn_Monster> MC;
local byte i;
local vector V;
local rotator R;
local Controller C;
local Ext_T_MonsterPRI PRI;
local AkBaseSoundObject TempSound;
local bool bFinalWave;
if( PawnOwner.PlayerReplicationInfo==None || !HasLiveZeds() )
{
RespawnHelperTime = 3;
return;
}
NoLiveCounter = 5;
bFinalWave = KFGameReplicationInfo(WorldInfo.GRI).IsFinalWave();
if( bFinalWave && Class<KFPawn_MonsterBoss>(PrevMonster)!=None )
PrevMonster = None;
MC = (PrevMonster!=None ? PrevMonster : PickRandomMonster(CurLevel,bFinalWave));
if( MC!=None )
{
R.Yaw = Rand(65536);
if( MC.Default.SoundGroupArch!=None )
{
// Make no entrance roam (for FP's and Scrakes).
TempSound = MC.Default.SoundGroupArch.EntranceSound;
MC.Default.SoundGroupArch.EntranceSound = None;
}
for( i=0; i<40; ++i )
{
V = PawnOwner.Location;
V.X += (FRand()*300.f-150.f);
V.Y += (FRand()*300.f-150.f);
if( !PawnOwner.FastTrace(V,PawnOwner.Location) )
continue;
LiveHelper = Spawn(MC,,,V,R);
if( LiveHelper!=None )
break;
}
if( MC.Default.SoundGroupArch!=None )
MC.Default.SoundGroupArch.EntranceSound = TempSound;
}
if( LiveHelper==None )
RespawnHelperTime = 2;
else
{
// Downscale.
LiveHelper.SetDrawScale(LiveHelper.DrawScale*FriendlyScalar);
LiveHelper.SetCollisionSize(LiveHelper.GetCollisionRadius()*FriendlyScalar,LiveHelper.GetCollisionHeight()*FriendlyScalar);
// Setup AI
C = Spawn(LiveHelper.ControllerClass);
if( KFAIController(C)!=None )
{
KFAIController(C).bCanTeleportCloser = false;
KFAIController(C).DefaultCommandClass = class'Ext_AICommandBasePet';
KFAIController(C).StuckCheckInterval = 100000.f; // ~27 hours
KFAIController(C).LastStuckCheckTime = WorldInfo.TimeSeconds;
}
LiveHelper.SpecialMoveHandler.SpecialMoveClasses[SM_Taunt] = class'Ext_AINoTaunt';
C.Possess(LiveHelper,false);
// Set HP.
LiveHelper.HealthMax = Clamp(LiveHelper.Default.Health,180,900)*HPScale;
LiveHelper.Health = LiveHelper.HealthMax;
LiveHelper.DamageScaling = DamageScale;
LiveHelper.SetWeakGrabCoolDown(28800.f); // Never get grabbed (for 80 hours).
LiveHelper.bWeakZedGrab = true;
LiveHelper.bCanGrabAttack = false;
// Scale by previous zed HP.
if( PrevMonster!=None )
{
LiveHelper.Health *= PrevMonsterHP;
PrevMonster = None;
}
// Setup PRI.
if( C.PlayerReplicationInfo!=None )
C.PlayerReplicationInfo.Destroy();
PRI = Spawn(class'Ext_T_MonsterPRI',LiveHelper);
LiveHelper.PlayerReplicationInfo = PRI;
C.PlayerReplicationInfo = PRI;
PRI.PawnOwner = LiveHelper;
PRI.HealthMax = LiveHelper.HealthMax;
PRI.MonsterName = Class'KFExtendedHUD'.Static.GetNameOf(MC);
PRI.OwnerPRI = PawnOwner.PlayerReplicationInfo;
PRI.MonsterType = MC;
PRI.PlayerName = PawnOwner.PlayerReplicationInfo.PlayerName$"'s "$PRI.MonsterName;
PRI.OwnerController = PawnOwner.Controller;
if( PawnOwner.PlayerReplicationInfo.Team!=None )
PawnOwner.PlayerReplicationInfo.Team.AddToTeam(C);
PRI.Timer();
if( WorldInfo.NetMode!=NM_DedicatedServer )
PRI.NotifyOwner();
}
}
final function SetDamageScale( float Sc )
{
DamageScale = Default.DamageScale*Sc;
if( LiveHelper!=None )
LiveHelper.DamageScaling = DamageScale;
}
final function SetHealthScale( float Sc )
{
HPScale = Default.HPScale*Sc;
}
static final function LoadMonsterList()
{
local int i,j;
local array<string> SA;
local class<KFPawn_Monster> C;
Default.ZedTypes.Length = class'Ext_TraitZED_Summon'.Default.ZedTypes.Length;
for( i=0; i<Default.ZedTypes.Length; ++i )
{
SA.Length = 0;
ParseStringIntoArray(class'Ext_TraitZED_Summon'.Default.ZedTypes[i],SA,",",true);
for( j=0; j<SA.Length; ++j )
{
C = class<KFPawn_Monster>(DynamicLoadObject(SA[j],Class'Class'));
if( C==None )
continue;
Default.ZedTypes[i].Zeds[Default.ZedTypes[i].Zeds.Length] = C;
}
if( Default.ZedTypes[i].Zeds.Length==0 )
Default.ZedTypes[i].Zeds[Default.ZedTypes[i].Zeds.Length] = Class'KFPawn_ZedClot_Alpha';
}
}
static final function class<KFPawn_Monster> PickRandomMonster( byte Level, bool bNotBoss )
{
local byte i;
local class<KFPawn_Monster> Res;
Level = Min(Default.ZedTypes.Length-1,Level);
for( i=0; i<5; ++i )
{
Res = Default.ZedTypes[Level].Zeds[Rand(Default.ZedTypes[Level].Zeds.Length)];
if( !bNotBoss || class<KFPawn_MonsterBoss>(Res)==None )
break;
}
if( bNotBoss && class<KFPawn_MonsterBoss>(Res)!=None )
Res = Class'KFPawn_ZedFleshpound';
return Res;
}
defaultproperties
{
RespawnHelperTime=1
HPScale=0.5
DamageScale=2
FriendlyScalar=0.65
}

View File

@ -0,0 +1,30 @@
Class Ext_TraitAirborne extends Ext_TraitBase;
var array<float> HealRates;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkFieldMedic(Perk).AirborneAgentHealRate = Default.HealRates[Level-1];
Ext_PerkFieldMedic(Perk).AirborneAgentLevel = (Level<4 ? 1 : 2);
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkFieldMedic(Perk).AirborneAgentLevel = 0;
}
defaultproperties
{
SupportedPerk=class'Ext_PerkFieldMedic'
TraitName="Airborne Agent"
DefLevelCosts(0)=20
DefLevelCosts(1)=10
DefLevelCosts(2)=10
DefLevelCosts(3)=60
HealRates(0)=0.05
HealRates(1)=0.1
HealRates(2)=0.2
HealRates(3)=0.15
NumLevels=4
DefMinLevel=50
Description="Give extra health boost and area of heal effect for medic darts during ZED-time,|each level gives extra amount of heal boost at a rate of:|Lv 1-3: +5%, +10%, +20%|Lv 4: +15%, but works outside of ZED-time too!"
}

View File

@ -0,0 +1,33 @@
Class Ext_TraitAmmoReg extends Ext_TraitBase;
var array<float> RegenValues;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Ext_T_AmmoRegHelp H;
H = Player.Spawn(class'Ext_T_AmmoRegHelp',Player);
if( H!=None )
H.RegCount = Default.RegenValues[Level-1];
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Ext_T_AmmoRegHelp H;
foreach Player.ChildActors(class'Ext_T_AmmoRegHelp',H)
H.Destroy();
}
defaultproperties
{
TraitGroup=class'Ext_TGroupRegen'
TraitName="Ammo Regeneration"
NumLevels=3
DefLevelCosts(0)=10
DefLevelCosts(1)=20
DefLevelCosts(2)=40
Description="With this trait all your weapons ammo (not grenades) will regen every half minute at rate of:|Lvl1-3: 2%, 5%, 10% of max ammo"
RegenValues.Add(0.02)
RegenValues.Add(0.05)
RegenValues.Add(0.1)
}

View File

@ -0,0 +1,27 @@
Class Ext_TraitArmorReg extends Ext_TraitHealthReg;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Ext_T_ArmorRegHelp H;
H = Player.Spawn(class'Ext_T_ArmorRegHelp',Player);
if( H!=None )
H.RegCount = Default.RegenValues[Level-1];
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Ext_T_ArmorRegHelp H;
foreach Player.ChildActors(class'Ext_T_ArmorRegHelp',H)
H.Destroy();
}
defaultproperties
{
TraitName="Armor Regeneration"
Description="With this trait your armor will regen every 10 seconds at a rate of:|Lvl1-3: +7pts, +12pts, +25pts"
RegenValues.Empty()
RegenValues.Add(7)
RegenValues.Add(12)
RegenValues.Add(25)
}

View File

@ -0,0 +1,23 @@
Class Ext_TraitArmorRep extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkFieldMedic(Perk).RepairArmorRate = float(Level)*0.05f;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkFieldMedic(Perk).RepairArmorRate = 0;
}
defaultproperties
{
SupportedPerk=class'Ext_PerkFieldMedic'
TraitName="Armor Repair"
NumLevels=5
DefLevelCosts(0)=10
DefLevelCosts(1)=15
DefLevelCosts(2)=20
DefLevelCosts(3)=25
DefLevelCosts(4)=35
Description="With this trait you will repair armor as you heal, for each level will repair armor with a rate of:|Lv1-5: +5%, +10%, +15%, +20%, +25%"
}

View File

@ -0,0 +1,23 @@
Class Ext_TraitAutoFire extends Ext_TraitBase;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Ext_T_AutoFireHelper H;
H = Player.Spawn(class'Ext_T_AutoFireHelper',Player);
H.AssociatedPerkClass = Perk.BasePerk;
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Ext_T_AutoFireHelper H;
foreach Player.ChildActors(class'Ext_T_AutoFireHelper',H)
H.Destroy();
}
defaultproperties
{
TraitName="Auto-Fire weapons"
DefLevelCosts(0)=50
Description="Make all perked weapons fully automatic."
}

View File

@ -0,0 +1,251 @@
Class Ext_TraitBase extends Object
abstract
config(ServerExt)
DependsOn(ExtWebAdmin_UI);
var array<FWebAdminConfigInfo> WebConfigs;
var() class<Ext_TGroupBase> TraitGroup; // With groups you can prevent player from buying multiple traits of same group.
var() string TraitName,Description; // UI name.
var() byte NumLevels; // Maximum number of levels.
var config array<int> LevelCosts;
var() array<int> DefLevelCosts; // Point price tag for each level.
var() class<Ext_TraitDataStore> TraitData; // Optional additional data that this trait requires for each player.
var config int MinLevel; // Minimum perk level player needs to be in order to be allowed to get this trait.
var() int DefMinLevel;
var() const byte LoadPriority; // Order of loading the trait class, if for example one trait depends on progress of another trait.
var() class<Ext_PerkBase> SupportedPerk; // Only functions on this perk.
// Config init stuff.
var config int ConfigVersion;
var const int CurrentConfigVer;
var config bool bDisabled; // This trait is currently disabled on server.
var() bool bGroupLimitToOne, // TraitGroup should limit so you can only buy one of them.
bHighPriorityDeath, // Should receive PreventDeath call before any other trait.
bPostApplyEffect; // Apply effects on second pass (relies on that another trait is activated first).
// Check if trait is enabled and usable on this perk.
static function bool IsEnabled( Ext_PerkBase Perk )
{
return !Default.bDisabled && (Default.SupportedPerk==None || ClassIsChildOf(Perk.Class,Default.SupportedPerk));
}
// Check if player meets the requirements to buy this trait.
static function bool MeetsRequirements( byte Lvl, Ext_PerkBase Perk )
{
// First check level.
if( Perk.CurrentLevel<Default.MinLevel )
return false;
// Then check grouping.
if( Lvl==0 && Default.TraitGroup!=None && Default.TraitGroup.Static.GroupLimited(Perk,Default.Class) )
return false;
return true;
}
// Return UI description player will see before bying this trait.
static function string GetPerkDescription()
{
local string S;
local byte i;
for( i=0; i<Default.NumLevels; ++i )
{
if( i==0 )
S = string(GetTraitCost(i));
else S $= ", "$GetTraitCost(i);
}
S = "Max level: #{9FF781}"$Default.NumLevels$"#{DEF}|Level costs: #{F3F781}"$S$"#{DEF}";
if( Default.MinLevel>0 )
S = "Min perk level: #{FF4000}"$Default.MinLevel$"#{DEF}|"$S;
return Default.Description$"||"$S;
}
// Return tooltip description of this trait
static function string GetTooltipInfo()
{
return Default.TraitName$"|"$Default.Description;
}
// Return level specific trait prices.
static function int GetTraitCost( byte LevelNum )
{
if( Default.LevelCosts.Length>0 )
{
if( LevelNum<Default.LevelCosts.Length )
return Default.LevelCosts[LevelNum];
return Default.LevelCosts[Default.LevelCosts.Length-1];
}
return 5;
}
// Trait initialization/cleanup.
static function Ext_TraitDataStore InitializeFor( Ext_PerkBase Perk, ExtPlayerController Player )
{
local Ext_TraitDataStore T;
T = None;
if( Default.TraitData!=None )
{
T = Player.Spawn(Default.TraitData,Player);
T.Perk = Perk;
T.PlayerOwner = Player;
T.TraitClass = Default.Class;
}
return T;
}
static function CleanupTrait( ExtPlayerController Player, Ext_PerkBase Perk, optional Ext_TraitDataStore Data )
{
if( Data!=None )
Data.Destroy();
}
// Called when trait is first activated/deactivated (might even have a dead pawn).
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
// Called everytime player spawns in on the game (cancel effect is called on level up/level reset/perk change).
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
// Owner died with this trait active.
static function PlayerDied( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
// Prevent death.
static function bool PreventDeath( KFPawn_Human Player, Controller Instigator, Class<DamageType> DamType, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
// Give/modify default inventory.
static function AddDefaultInventory( KFPawn Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
// Data that server should replicate to client.
static final function string IntToStr( int Value, optional byte MaxVal ) // Helper function to put integer into one character of string.
{
switch( MaxVal )
{
case 0: // 0-65535
return Chr(Max(Value,0)+1);
case 1: // 0-1073741823
return Chr((Value & 32767)+1) $ Chr(((Value >> 15) & 32767)+1);
}
}
static final function string InlineString( string Str ) // Helper function to append a string line to a text using a length char in front.
{
return IntToStr(Len(Str))$Str;
}
static final function int StrToInt( out string Value, optional byte MaxVal ) // Reverse.
{
local int Res;
switch( MaxVal )
{
case 0: // 0-65535
Res = Asc(Left(Value,1))-1;
Value = Mid(Value,1);
break;
case 1: // 0-1073741823
Res =(Asc(Mid(Value,0,1))-1) | ((Asc(Mid(Value,1,1)) << 15)-1);
Value = Mid(Value,2);
break;
}
return Res;
}
static final function string GetInlineStr( out string S ) // Reverse.
{
local int l;
local string Res;
l = StrToInt(S);
Res = Left(S,l);
S = Mid(S,l);
return Res;
}
static function string GetRepData()
{
local string S;
local int i;
S = IntToStr(Default.MinLevel)$IntToStr(Default.LevelCosts.Length);
for( i=0; i<Default.LevelCosts.Length; ++i )
S $= IntToStr(Default.LevelCosts[i]);
return S;
}
static function string ClientSetRepData( string S )
{
local int i;
Default.MinLevel = StrToInt(S);
Default.LevelCosts.Length = StrToInt(S);
for( i=0; i<Default.LevelCosts.Length; ++i )
Default.LevelCosts[i] = StrToInt(S);
return S;
}
// Configure initialization.
static function CheckConfig()
{
if( Default.ConfigVersion!=Default.CurrentConfigVer )
{
UpdateConfigs(Default.ConfigVersion);
Default.ConfigVersion = Default.CurrentConfigVer;
StaticSaveConfig();
}
}
static function UpdateConfigs( int OldVer )
{
if( OldVer==0 )
{
Default.LevelCosts = Default.DefLevelCosts;
Default.MinLevel = Default.DefMinLevel;
}
}
// WebAdmin UI
static function InitWebAdmin( ExtWebAdmin_UI UI )
{
UI.AddSettingsPage("Trait "$Default.TraitName,Default.Class,Default.WebConfigs,GetValue,ApplyValue);
}
static function string GetValue( name PropName, int ElementIndex )
{
switch( PropName )
{
case 'MinLevel':
return string(Default.MinLevel);
case 'LevelCosts':
return (ElementIndex==-1 ? string(Default.LevelCosts.Length) : string(Default.LevelCosts[ElementIndex]));
case 'bDisabled':
return string(Default.bDisabled);
}
}
static function ApplyValue( name PropName, int ElementIndex, string Value )
{
switch( PropName )
{
case 'MinLevel':
Default.MinLevel = int(Value); break;
case 'LevelCosts':
Default.LevelCosts.Length = Default.DefLevelCosts.Length;
if( Value!="#DELETE" && ElementIndex<Default.LevelCosts.Length )
Default.LevelCosts[ElementIndex] = int(Value);
break;
case 'bDisabled':
Default.bDisabled = bool(Value); break;
default:
return;
}
StaticSaveConfig();
}
defaultproperties
{
CurrentConfigVer=1
DefLevelCosts.Add(5)
NumLevels=1
DefMinLevel=0
WebConfigs.Add((PropType=1,PropName="bDisabled",UIName="Disabled",UIDesc="Disable this trait (hides from UI and makes it unusable)!"))
WebConfigs.Add((PropType=0,PropName="MinLevel",UIName="Minimum Level",UIDesc="Minimum Level required for this trait"))
WebConfigs.Add((PropType=0,PropName="LevelCosts",UIName="Level Costs",UIDesc="EXP cost for each trait level (array length is a constant)!",NumElements=-1))
}

View File

@ -0,0 +1,18 @@
Class Ext_TraitBoomWeld extends Ext_TraitBase
abstract;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bExplosiveWeld = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bExplosiveWeld = false;
}
defaultproperties
{
TraitName="Explosive Weld"
DefLevelCosts(0)=30
Description="Cases welded doors explode when broken by zeds. The more you weld one door, the bigger explosion."
}

View File

@ -0,0 +1,20 @@
Class Ext_TraitBunnyHop extends Ext_TraitBase;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).bHasBunnyHop = true;
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).bHasBunnyHop = false;
}
defaultproperties
{
TraitName="Bunny Hop"
DefLevelCosts(0)=50
DefMinLevel=100
Description="Enable player to do bunny hopping. It means the more you continiously make successful jumps while moving forward you will keep accelerating in speed."
}

View File

@ -0,0 +1,37 @@
Class Ext_TraitCarryCap extends Ext_TraitBase;
var array<byte> CarryAdds;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local KFInventoryManager M;
M = KFInventoryManager(Player.InvManager);
if( M!=None )
M.MaxCarryBlocks = M.Default.MaxCarryBlocks+Default.CarryAdds[Level-1];
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local KFInventoryManager M;
M = KFInventoryManager(Player.InvManager);
if( M!=None )
M.MaxCarryBlocks = M.Default.MaxCarryBlocks;
}
defaultproperties
{
TraitName="Carry Capacity"
NumLevels=5
DefLevelCosts(0)=10
DefLevelCosts(1)=15
DefLevelCosts(2)=20
DefLevelCosts(3)=25
DefLevelCosts(4)=50
Description="With this trait you can carry more.|Lv1-5: +2,+4,+6,+8,+15 slots"
CarryAdds.Add(2)
CarryAdds.Add(4)
CarryAdds.Add(6)
CarryAdds.Add(8)
CarryAdds.Add(15)
}

View File

@ -0,0 +1,17 @@
Class Ext_TraitContactNade extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bExplodeOnContact = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bExplodeOnContact = false;
}
defaultproperties
{
TraitName="Explode on Contact"
DefLevelCosts(0)=25
Description="Make dynamites explode on contact with the ZED."
}

View File

@ -0,0 +1,11 @@
// Optional additional player specific data for a trait.
Class Ext_TraitDataStore extends Info
abstract;
var Ext_PerkBase Perk;
var ExtPlayerController PlayerOwner;
var class<Ext_TraitBase> TraitClass;
defaultproperties
{
}

View File

@ -0,0 +1,18 @@
Class Ext_TraitDireReload extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkSharpshooter(Perk).bHasDireReload = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkSharpshooter(Perk).bHasDireReload = false;
}
defaultproperties
{
SupportedPerk=class'Ext_PerkSharpshooter'
TraitName="Dire reloader"
DefLevelCosts(0)=35
Description="This trait will make you reload much faster when you have less then 40 health."
}

View File

@ -0,0 +1,29 @@
Class Ext_TraitDuracell extends Ext_TraitBase;
var array<float> BatteryCharges;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).SetBatteryRate(Default.BatteryCharges[Level-1]);
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).SetBatteryRate(1.f);
}
defaultproperties
{
TraitName="Duracell Batteries"
NumLevels=4
DefLevelCosts(0)=5
DefLevelCosts(1)=10
DefLevelCosts(2)=20
DefLevelCosts(3)=25
Description="With this trait your flashlight batteries becomes extra durable.|Lv1-4: +30,+100,+300,+1000% lifetime"
BatteryCharges.Add(0.77)
BatteryCharges.Add(0.5)
BatteryCharges.Add(0.333)
BatteryCharges.Add(0.1)
}

View File

@ -0,0 +1,18 @@
Class Ext_TraitEliteReload extends Ext_TraitBase;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bTacticalReload = true;
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bTacticalReload = false;
}
defaultproperties
{
TraitName="Tactical Reload"
DefLevelCosts(0)=50
Description="With this trait you will have extra speedy tactical reload moves for your perked weapons."
DefMinLevel=50
}

View File

@ -0,0 +1,21 @@
Class Ext_TraitEnemyHP extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.EnemyHealthRange = Level;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.EnemyHealthRange = 0;
}
defaultproperties
{
TraitName="Enemy Health Bar"
NumLevels=4
DefLevelCosts(0)=25
DefLevelCosts(1)=15
DefLevelCosts(2)=20
DefLevelCosts(3)=30
Description="This trait lets you see enemy health bars. The distance is increased by every level in:|Lv1-4: 5m, 7m, 10m, 16m"
}

View File

@ -0,0 +1,18 @@
Class Ext_TraitFanfire extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkGunslinger(Perk).bHasFanfire = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkGunslinger(Perk).bHasFanfire = false;
}
defaultproperties
{
SupportedPerk=class'Ext_PerkGunslinger'
TraitName="ZED TIME - Fanfire"
DefLevelCosts(0)=30
Description="Make perked weapons fire at normal firerate during ZED-time."
}

View File

@ -0,0 +1,17 @@
Class Ext_TraitFireExplode extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bFireExplode = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bFireExplode = false;
}
defaultproperties
{
TraitName="Fire Explosion"
DefLevelCosts(0)=50
Description="Make zombies sometimes explode when burned to death."
}

View File

@ -0,0 +1,17 @@
Class Ext_TraitFireRange extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
KFPlayerReplicationInfo(Perk.PlayerOwner.PlayerReplicationInfo).bExtraFireRange = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
KFPlayerReplicationInfo(Perk.PlayerOwner.PlayerReplicationInfo).bExtraFireRange = false;
}
defaultproperties
{
TraitName="Extra Fire Range"
DefLevelCosts(0)=35
Description="Add some additional fire range to flamethrowers."
}

View File

@ -0,0 +1,34 @@
Class Ext_TraitGhost extends Ext_TraitBase;
static function bool PreventDeath( KFPawn_Human Player, Controller Instigator, Class<DamageType> DamType, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Controller C;
if( (Instigator==None || Instigator==Player.Controller) && DamType==Class'DmgType_Suicided' )
return false; // Allow normal suicide to go ahead.
if( Ext_T_GhostHelper(Data).CanResPlayer(Player,Level) )
{
// Abort current special move
if( Player.IsDoingSpecialMove() )
Player.SpecialMoveHandler.EndSpecialMove();
// Notify AI to stop hunting me.
foreach Player.WorldInfo.AllControllers(class'Controller',C)
C.NotifyKilled(Instigator,Player.Controller,Player,DamType);
return true;
}
return false;
}
defaultproperties
{
bHighPriorityDeath=true
NumLevels=2
TraitData=class'Ext_T_GhostHelper'
TraitName="Redemption"
DefLevelCosts(0)=30
DefLevelCosts(1)=30
DefMinLevel=30
Description="With this trait you will turn into ghost when you die and redeem at another spot in the map.|Level 1: Works 50 % of the time, but never again until you respawned after death.|Level 2: Always works, and it lets you redeem again after 3 minutes"
}

View File

@ -0,0 +1,29 @@
Class Ext_TraitGrenadeCap extends Ext_TraitCarryCap;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data );
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.PerkManager.SetGrenadeCap(Default.CarryAdds[Level-1]);
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.PerkManager.SetGrenadeCap(0);
}
defaultproperties
{
TraitName="Grenade Capacity"
DefLevelCosts(0)=40
DefLevelCosts(1)=55
DefLevelCosts(2)=70
DefLevelCosts(3)=90
DefLevelCosts(4)=150
Description="With this trait you can carry more grenades.|Lv1-5: +1,+2,+3,+5,+8 grenades"
CarryAdds(0)=1
CarryAdds(1)=2
CarryAdds(2)=3
CarryAdds(3)=5
CarryAdds(4)=8
}

View File

@ -0,0 +1,19 @@
Class Ext_TraitGrenadeSUpg extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( Level==1 )
Perk.GrenadeClass = Perk.SuperGrenade;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.GrenadeClass = Perk.Default.GrenadeClass;
}
defaultproperties
{
TraitName="Grenade Upgrade"
DefLevelCosts(0)=50
Description="With this upgrade you will upgrade to your perk specific grenades.|Level 1: SUPER grenade"
DefMinLevel=50
}

View File

@ -0,0 +1,28 @@
Class Ext_TraitGrenadeUpg extends Ext_TraitBase;
static function bool MeetsRequirements( byte Lvl, Ext_PerkBase Perk )
{
if( Lvl>=1 && Perk.CurrentLevel<50 )
return false;
return Super.MeetsRequirements(Lvl,Perk);
}
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( Level==1 )
Perk.GrenadeClass = Perk.PerkGrenade;
else if( Level==2 )
Perk.GrenadeClass = Perk.SuperGrenade;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.GrenadeClass = Perk.Default.GrenadeClass;
}
defaultproperties
{
TraitName="Grenade Upgrade"
NumLevels=2
DefLevelCosts(0)=5
DefLevelCosts(1)=50
Description="With this upgrade you will upgrade to your perk specific grenades.|Level 1: Normal perk grenade|Level 2: Perk SUPER grenade (REQUIRES perk level 50 to buy)!"
}

View File

@ -0,0 +1,33 @@
Class Ext_TraitHealthReg extends Ext_TraitBase;
var array<byte> RegenValues;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Ext_T_HealthRegHelp H;
H = Player.Spawn(class'Ext_T_HealthRegHelp',Player);
if( H!=None )
H.RegCount = Default.RegenValues[Level-1];
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local Ext_T_HealthRegHelp H;
foreach Player.ChildActors(class'Ext_T_HealthRegHelp',H)
H.Destroy();
}
defaultproperties
{
TraitGroup=class'Ext_TGroupRegen'
TraitName="Health Regeneration"
NumLevels=3
DefLevelCosts(0)=10
DefLevelCosts(1)=20
DefLevelCosts(2)=40
Description="With this trait your health will regen every 10 seconds at a rate of:|Lvl1-3: +5HP, +10HP, +20HP"
RegenValues.Add(5)
RegenValues.Add(10)
RegenValues.Add(20)
}

View File

@ -0,0 +1,21 @@
Class Ext_TraitHeavyArmor extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bHeavyArmor = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bHeavyArmor = false;
}
defaultproperties
{
TraitName="Heavy Armor"
NumLevels=3
DefLevelCosts(0)=50
DefLevelCosts(1)=20
DefLevelCosts(2)=60
DefMinLevel=50
Description="Makes your armor stop all damage (except for Siren scream and fall damage).|Level 2 makes you in addition spawn with 50 points of armor.|Level 3 makes you spawn with full armor."
}

View File

@ -0,0 +1,29 @@
Class Ext_TraitKnockback extends Ext_TraitRagdoll;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).KnockbackResist = Default.ChanceValues[Level-1];
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).KnockbackResist = 1.f;
}
defaultproperties
{
TraitName="Knockback Resistance"
NumLevels=4
DefLevelCosts(0)=30
DefLevelCosts(1)=30
DefLevelCosts(2)=40
DefLevelCosts(3)=60
DefMinLevel=70
Description="Reduce the amount of knockback zeds do to you in a rate of:|Lvl1-4: -20%, -50%, -70%, -90%"
ChanceValues(0)=0.8
ChanceValues(1)=0.5
ChanceValues(2)=0.3
ChanceValues(3)=0.1
}

View File

@ -0,0 +1,14 @@
Class Ext_TraitMedicPistol extends Ext_TraitBase;
static function AddDefaultInventory( KFPawn Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Player.DefaultInventory.RemoveItem(class'KFWeap_Pistol_9mm');
Player.DefaultInventory.AddItem(class'KFWeap_Pistol_Medic');
}
defaultproperties
{
TraitName="Medic Pistol"
DefLevelCosts(0)=20
Description="Spawn with a medic pistol instead of standard 9mm."
}

View File

@ -0,0 +1,17 @@
Class Ext_TraitNapalm extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bNapalmFire = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bNapalmFire = false;
}
defaultproperties
{
TraitName="Napalm"
DefLevelCosts(0)=35
Description="Make zombies lit each other on fire."
}

View File

@ -0,0 +1,18 @@
Class Ext_TraitNightvision extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bHasNightVision = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bHasNightVision = false;
}
defaultproperties
{
TraitName="Nightvision"
NumLevels=1
DefLevelCosts(0)=25
Description="Spawn with nightvision goggles."
}

View File

@ -0,0 +1,30 @@
Class Ext_TraitRackEmUp extends Ext_TraitBase;
var array<byte> ComboSize;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkRhythmPerkBase(Perk).SetMaxRhythm(Default.ComboSize[Level-1]);
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkRhythmPerkBase(Perk).ResetRhythm();
}
defaultproperties
{
SupportedPerk=class'Ext_PerkRhythmPerkBase'
TraitName="Rack 'em up"
DefLevelCosts(0)=10
DefLevelCosts(1)=15
DefLevelCosts(2)=20
DefLevelCosts(3)=30
DefLevelCosts(4)=50
ComboSize.Add(4)
ComboSize.Add(8)
ComboSize.Add(12)
ComboSize.Add(16)
ComboSize.Add(28)
NumLevels=5
Description="Deals more damage to each consequtive headshot done to zeds by +7.5%.|For each level you can make a bigger combo and deal more damage in a rate of:|Lv1-5: +30%, +60%, +90%, +120%, +210%"
}

View File

@ -0,0 +1,29 @@
Class Ext_TraitRagdoll extends Ext_TraitBase;
var float ChanceValues[4];
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).NoRagdollChance = Default.ChanceValues[Level-1];
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).NoRagdollChance = 0.f;
}
defaultproperties
{
TraitName="Knockout Resistance"
NumLevels=3
DefLevelCosts(0)=30
DefLevelCosts(1)=30
DefLevelCosts(2)=40
DefMinLevel=100
Description="Prevent you from being ragdolled. For each level you lower the chance of being knocked out by:|Lvl1-3: 20%, 50%, 80%"
ChanceValues(0)=0.2
ChanceValues(1)=0.5
ChanceValues(2)=0.8
}

View File

@ -0,0 +1,18 @@
Class Ext_TraitRanger extends Ext_TraitBase;
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkSharpshooter(Perk).ZEDTimeStunPower = 4.f;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_PerkSharpshooter(Perk).ZEDTimeStunPower = 0.f;
}
defaultproperties
{
SupportedPerk=class'Ext_PerkSharpshooter'
TraitName="ZED TIME - Ranger"
DefLevelCosts(0)=40
Description="This will make you effectively stun enemies with headshots during ZED-time."
}

View File

@ -0,0 +1,23 @@
Class Ext_TraitRetali extends Ext_TraitBase;
static function bool PreventDeath( KFPawn_Human Player, Controller Instigator, Class<DamageType> DamType, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
local ExtProj_SUPERGrenade P;
P = Player.Spawn(class'ExtProj_SUPERGrenade');
if( P!=None )
{
P.bExplodeOnContact = false; // Nope!
P.InstigatorController = Player.Controller;
P.ClusterNades = class'ExtProj_CrackerGrenade';
}
return false;
}
defaultproperties
{
TraitName="Retaliation"
DefLevelCosts(0)=50
DefMinLevel=40
Description="End your life with a BOOM!"
}

View File

@ -0,0 +1,27 @@
Class Ext_TraitSWATEnforcer extends Ext_TraitBase;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).bMovesFastInZedTime = true;
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).bMovesFastInZedTime = false;
}
static function TraitActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bHasSWATEnforcer = true;
}
static function TraitDeActivate( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Perk.bHasSWATEnforcer = false;
}
defaultproperties
{
TraitName="ZED TIME - SWAT Enforcer"
DefLevelCosts(0)=50
Description="This trait makes you move at normal speed and allows you to knock down zeds by bumping into them during ZED-time."
}

View File

@ -0,0 +1,31 @@
Class Ext_TraitSpartan extends Ext_TraitBase;
var array<float> AtkRates;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).bMovesFastInZedTime = true;
Ext_PerkBerserker(Perk).ZedTimeMeleeAtkRate = 1.f/Default.AtkRates[Level-1];
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
if( ExtHumanPawn(Player)!=None )
ExtHumanPawn(Player).bMovesFastInZedTime = false;
Ext_PerkBerserker(Perk).ZedTimeMeleeAtkRate = 1.f;
}
defaultproperties
{
SupportedPerk=class'Ext_PerkBerserker'
TraitName="ZED TIME - Spartan!"
NumLevels=3
DefLevelCosts(0)=50
DefLevelCosts(1)=40
DefLevelCosts(2)=80
Description="This trait lets you move at normal speed and attack faster in ZED-time.|Lv1-3: +50,+120,+300% atk speed"
AtkRates.Add(1.5)
AtkRates.Add(2.2)
AtkRates.Add(4.0)
DefMinLevel=100
}

View File

@ -0,0 +1,26 @@
Class Ext_TraitSupply extends Ext_TraitBase;
var() Texture2D SupplyIcon;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_TraitSupplyData(Data).SpawnSupplier(Player);
}
static function CancelEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_TraitSupplyData(Data).RemoveSupplier();
}
static function PlayerDied( Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_TraitSupplyData(Data).RemoveSupplier();
}
defaultproperties
{
TraitName="Ammunition Supply"
DefLevelCosts(0)=50
Description="With this trait you can supply ammunition for your team mates. For each use you will receive a little bit of XP points."
TraitData=class'Ext_TraitSupplyData'
SupplyIcon=Texture2D'UI_World_TEX.Support_Supplier_HUD'
}

View File

@ -0,0 +1,30 @@
Class Ext_TraitSupplyData extends Ext_TraitDataStore;
var Ext_T_SupplierInteract SupplyInteraction;
final function SpawnSupplier( KFPawn_Human H, optional bool bGrenades )
{
if( SupplyInteraction!=None )
SupplyInteraction.Destroy();
SupplyInteraction = Spawn( class'Ext_T_SupplierInteract', H,, H.Location, H.Rotation,, true );
SupplyInteraction.SetBase( H );
SupplyInteraction.PlayerOwner = H;
SupplyInteraction.PerkOwner = Perk;
SupplyInteraction.bGrenades = bGrenades;
if( PlayerOwner!=None && ExtPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo)!=None )
ExtPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo).HasSupplier = class<Ext_TraitSupply>(TraitClass);
}
final function RemoveSupplier()
{
if( SupplyInteraction!=None )
SupplyInteraction.Destroy();
if( PlayerOwner!=None && ExtPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo)!=None )
ExtPlayerReplicationInfo(PlayerOwner.PlayerReplicationInfo).HasSupplier = None;
}
function Destroyed()
{
RemoveSupplier();
}

View File

@ -0,0 +1,14 @@
Class Ext_TraitSupplyGren extends Ext_TraitSupply;
static function ApplyEffectOn( KFPawn_Human Player, Ext_PerkBase Perk, byte Level, optional Ext_TraitDataStore Data )
{
Ext_TraitSupplyData(Data).SpawnSupplier(Player,true);
}
defaultproperties
{
TraitName="Grenade Supply"
Description="With this trait you can supply grenades for your team mates. For each use you will receive a little bit of XP points."
SupplyIcon=Texture2D'UI_World_TEX.Demolitionist_Supplier_HUD'
}

Some files were not shown because too many files have changed in this diff Show More