Updated to the latest KF version

This commit is contained in:
ForrestMarkX 2020-01-09 05:05:13 -06:00
parent fd568e3d66
commit 245eb9e552
12 changed files with 1408 additions and 1044 deletions

View File

@ -230,7 +230,7 @@ function int AddItemByPriority( out SItemInformation WeaponInfo )
return BestIndex; return BestIndex;
} }
function bool CanCarry( const out STraderItem Item ) function bool CanCarry(const out STraderItem Item, optional int OverrideLevelValue = INDEX_NONE)
{ {
local int Result; local int Result;

View File

@ -36,6 +36,51 @@ static final function Object SafeLoadObject( string S, Class ObjClass )
return O!=None ? O : DynamicLoadObject(S,ObjClass); return O!=None ? O : DynamicLoadObject(S,ObjClass);
} }
static function InitCharacterMICs(KFCharacterInfo_Human C, KFPawn P, optional bool bMaskHead)
{
local int i;
if( P.WorldInfo.NetMode == NM_DedicatedServer )
{
return;
}
P.CharacterMICs.Remove(0, P.CharacterMICs.Length);
// body MIC
if ( P.Mesh != None )
{
P.CharacterMICs[0] = P.Mesh.CreateAndSetMaterialInstanceConstant(C.BodyMaterialID);
CloneMIC(P.CharacterMICs[0]);
}
// head MIC
if( P.ThirdPersonHeadMeshComponent != None )
{
P.CharacterMICs[1] = P.ThirdPersonHeadMeshComponent.CreateAndSetMaterialInstanceConstant(C.HeadMaterialID);
if ( bMaskHead )
{
// initial mask for new head MIC (also see ResetHeadMaskParam())
P.CharacterMICs[1].SetScalarParameterValue('Scalar_Mask', 1.f);
}
}
// attachment MIC
for( i=0; i < `MAX_COSMETIC_ATTACHMENTS; i++ )
{
if( P.ThirdPersonAttachments[i] != none )
{
P.CharacterMICs.AddItem(P.ThirdPersonAttachments[i].CreateAndSetMaterialInstanceConstant(0));
}
if (P.FirstPersonAttachments[i] != none)
{
P.CharacterMICs.AddItem(P.FirstPersonAttachments[i].CreateAndSetMaterialInstanceConstant(0));
}
}
}
/** Sets the pawns character mesh from it's CharacterInfo, and updates instance of player in map if there is one. */ /** 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 ) static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI )
{ {
@ -43,25 +88,27 @@ static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn
local int AttachmentIdx, CosmeticMeshIdx; local int AttachmentIdx, CosmeticMeshIdx;
local bool bMaskHeadMesh, bCustom; local bool bMaskHeadMesh, bCustom;
EPRI = ExtPlayerReplicationInfo(KFPRI);
if ( KFPRI == none ) if ( KFPRI == none )
{ {
`Warn("Does not have a KFPRI" @ C); `Warn("Does not have a KFPRI" @ C);
return; return;
} }
EPRI = ExtPlayerReplicationInfo(KFPRI);
bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false); bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false);
// Body mesh & skin. Index of 255 implies use index 0 (default). // Body mesh & skin. Index of 255 implies use index 0 (default).
SetBodyMeshAndSkin(C, SetBodyMeshAndSkin(C,
bCustom ? EPRI.CustomCharacter.BodyMeshIndex : KFPRI.RepCustomizationInfo.BodyMeshIndex, bCustom ? EPRI.CustomCharacter.BodyMeshIndex : KFPRI.RepCustomizationInfo.BodyMeshIndex,
bCustom ? EPRI.CustomCharacter.BodySkinIndex : KFPRI.RepCustomizationInfo.BodySkinIndex, bCustom ? EPRI.CustomCharacter.BodySkinIndex : KFPRI.RepCustomizationInfo.BodySkinIndex,
KFP); KFP,
KFPRI);
// Head mesh & skin. Index of 255 implies use index 0 (default). // Head mesh & skin. Index of 255 implies use index 0 (default).
SetHeadMeshAndSkin(C, SetHeadMeshAndSkin(C,
bCustom ? EPRI.CustomCharacter.HeadMeshIndex : KFPRI.RepCustomizationInfo.HeadMeshIndex, bCustom ? EPRI.CustomCharacter.HeadMeshIndex : KFPRI.RepCustomizationInfo.HeadMeshIndex,
bCustom ? EPRI.CustomCharacter.HeadSkinIndex : KFPRI.RepCustomizationInfo.HeadSkinIndex, bCustom ? EPRI.CustomCharacter.HeadSkinIndex : KFPRI.RepCustomizationInfo.HeadSkinIndex,
KFP); KFP,
KFPRI);
// skip dedicated for purely cosmetic stuff // skip dedicated for purely cosmetic stuff
if ( KFP.WorldInfo.NetMode != NM_DedicatedServer ) if ( KFP.WorldInfo.NetMode != NM_DedicatedServer )
@ -78,7 +125,7 @@ static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn
for( AttachmentIdx=0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ ) for( AttachmentIdx=0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ )
{ {
CosmeticMeshIdx = bCustom ? EPRI.CustomCharacter.AttachmentMeshIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx]; CosmeticMeshIdx = bCustom ? EPRI.CustomCharacter.AttachmentMeshIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx];
if ( CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX ) if ( CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX && CosmeticMeshIdx != INDEX_NONE )
{ {
bMaskHeadMesh = bMaskHeadMesh || C.CosmeticVariants[CosmeticMeshIdx].bMaskHeadMesh; bMaskHeadMesh = bMaskHeadMesh || C.CosmeticVariants[CosmeticMeshIdx].bMaskHeadMesh;
@ -91,29 +138,49 @@ static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn
} }
// initial mask for new MIC (also see ResetHeadMaskParam()) // initial mask for new MIC (also see ResetHeadMaskParam())
if ( bMaskHeadMesh && KFP.CharacterMICs[1] != None ) InitCharacterMICs(C, KFP, bMaskHeadMesh);
KFP.CharacterMICs[1].SetScalarParameterValue('Scalar_Mask', 1.f);
} }
} }
static final function SetBodyMeshAndSkin( KFCharacterInfo_Human C, static final function SetBodyMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentBodyMeshIndex, byte CurrentBodyMeshIndex,
byte CurrentBodySkinIndex, byte CurrentBodySkinIndex,
KFPawn KFP ) KFPawn KFP,
KFPlayerReplicationInfo KFPRI )
{ {
local string CharBodyMeshName;
local SkeletalMesh CharBodyMesh; local SkeletalMesh CharBodyMesh;
//Always use default body on servers
if (KFP.WorldInfo.NetMode == NM_DedicatedServer)
{
CurrentBodyMeshIndex = 0;
CurrentBodySkinIndex = 0;
}
// Character Mesh // Character Mesh
if( C.BodyVariants.length > 0 ) if( C.BodyVariants.length > 0 )
{ {
// Assign a skin to the body mesh as a material override // Assign a skin to the body mesh as a material override
CurrentBodyMeshIndex = (CurrentBodyMeshIndex < C.BodyVariants.length) ? CurrentBodyMeshIndex : 0; CurrentBodyMeshIndex = (CurrentBodyMeshIndex < C.BodyVariants.length) ? CurrentBodyMeshIndex : 0;
if (KFPRI.StartLoadCosmeticContent(C, ECOSMETICTYPE_Body, CurrentBodyMeshIndex))
{
return;
}
// Retrieve the name of the meshes to be used from the archetype
CharBodyMeshName = C.BodyVariants[CurrentBodyMeshIndex].MeshName;
// Load the meshes // Load the meshes
CharBodyMesh = SkeletalMesh(SafeLoadObject(C.BodyVariants[CurrentBodyMeshIndex].MeshName, class'SkeletalMesh')); CharBodyMesh = SkeletalMesh(SafeLoadObject(CharBodyMeshName, class'SkeletalMesh'));
// Assign the body mesh to the pawn // Assign the body mesh to the pawn
if ( CharBodyMesh != KFP.Mesh.SkeletalMesh )
{
KFP.Mesh.SetSkeletalMesh(CharBodyMesh); KFP.Mesh.SetSkeletalMesh(CharBodyMesh);
KFP.OnCharacterMeshChanged();
}
if (KFP.WorldInfo.NetMode != NM_DedicatedServer) if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
{ {
@ -146,13 +213,6 @@ static final function SetBodySkinMaterial( KFCharacterInfo_Human C, OutfitVarian
KFP.Mesh.SetMaterial(i, none); KFP.Mesh.SetMaterial(i, none);
} }
} }
// Initialize MICs
if( KFP.Mesh != None )
{
KFP.CharacterMICs[0] = KFP.Mesh.CreateAndSetMaterialInstanceConstant(C.BodyMaterialID);
CloneMIC(KFP.CharacterMICs[0]);
}
} }
} }
@ -176,20 +236,14 @@ static final function SetHeadSkinMaterial( KFCharacterInfo_Human C, OutfitVarian
KFP.ThirdPersonHeadMeshComponent.SetMaterial(i, none); 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, static final function SetHeadMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentHeadMeshIndex, byte CurrentHeadMeshIndex,
byte CurrentHeadSkinIndex, byte CurrentHeadSkinIndex,
KFPawn KFP ) KFPawn KFP,
KFPlayerReplicationInfo KFPRI )
{ {
local string CharHeadMeshName; local string CharHeadMeshName;
local SkeletalMesh CharHeadMesh; local SkeletalMesh CharHeadMesh;
@ -198,6 +252,11 @@ static final function SetHeadMeshAndSkin( KFCharacterInfo_Human C,
{ {
CurrentHeadMeshIndex = (CurrentHeadMeshIndex < C.HeadVariants.length) ? CurrentHeadMeshIndex : 0; CurrentHeadMeshIndex = (CurrentHeadMeshIndex < C.HeadVariants.length) ? CurrentHeadMeshIndex : 0;
if (KFPRI.StartLoadCosmeticContent(C, ECOSMETICTYPE_Head, CurrentHeadMeshIndex))
{
return;
}
CharHeadMeshName = C.HeadVariants[CurrentHeadMeshIndex].MeshName; CharHeadMeshName = C.HeadVariants[CurrentHeadMeshIndex].MeshName;
CharHeadMesh = SkeletalMesh(DynamicLoadObject(CharHeadMeshName, class'SkeletalMesh')); CharHeadMesh = SkeletalMesh(DynamicLoadObject(CharHeadMeshName, class'SkeletalMesh'));
@ -222,7 +281,8 @@ static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
int PawnAttachmentIndex, int PawnAttachmentIndex,
const out AttachmentVariants CurrentVariant, const out AttachmentVariants CurrentVariant,
byte NewSkinIndex, byte NewSkinIndex,
KFPawn KFP) KFPawn KFP,
optional bool bIsFirstPerson)
{ {
local int i; local int i;
if (KFP.WorldInfo.NetMode != NM_DedicatedServer) if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
@ -231,11 +291,23 @@ static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
{ {
// Assign a skin to the attachment mesh as a material override // Assign a skin to the attachment mesh as a material override
if ( NewSkinIndex < CurrentVariant.AttachmentItem.SkinVariations.length ) if ( NewSkinIndex < CurrentVariant.AttachmentItem.SkinVariations.length )
{
if (bIsFirstPerson)
{
if (KFP.FirstPersonAttachments[PawnAttachmentIndex] != none)
{
KFP.FirstPersonAttachments[PawnAttachmentIndex].SetMaterial(
CurrentVariant.AttachmentItem.SkinMaterialID,
CurrentVariant.AttachmentItem.SkinVariations[NewSkinIndex].Skin1p);
}
}
else
{ {
KFP.ThirdPersonAttachments[PawnAttachmentIndex].SetMaterial( KFP.ThirdPersonAttachments[PawnAttachmentIndex].SetMaterial(
CurrentVariant.AttachmentItem.SkinMaterialID, CurrentVariant.AttachmentItem.SkinMaterialID,
CurrentVariant.AttachmentItem.SkinVariations[NewSkinIndex].Skin); CurrentVariant.AttachmentItem.SkinVariations[NewSkinIndex].Skin);
} }
}
else else
{ {
`log("Out of bounds skin index for"@CurrentVariant.MeshName); `log("Out of bounds skin index for"@CurrentVariant.MeshName);
@ -243,6 +315,18 @@ static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
} }
} }
else else
{
if (bIsFirstPerson)
{
if (KFP.FirstPersonAttachments[PawnAttachmentIndex] != none)
{
for (i = 0; i < KFP.FirstPersonAttachments[PawnAttachmentIndex].GetNumElements(); i++)
{
KFP.FirstPersonAttachments[PawnAttachmentIndex].SetMaterial(i, none);
}
}
}
else
{ {
// Use material specified in the mesh asset // Use material specified in the mesh asset
for( i=0; i < KFP.ThirdPersonAttachments[PawnAttachmentIndex].GetNumElements(); i++ ) for( i=0; i < KFP.ThirdPersonAttachments[PawnAttachmentIndex].GetNumElements(); i++ )
@ -252,26 +336,19 @@ static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
} }
} }
} }
}
/** Called on owning client to change a cosmetic attachment or on other clients via replication */
static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C, static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentAttachmentMeshIndex, int CurrentAttachmentMeshIndex,
byte CurrentAttachmentSkinIndex, int CurrentAttachmentSkinIndex,
KFPawn KFP, KFPawn KFP,
optional KFPlayerReplicationInfo KFPRI ) KFPlayerReplicationInfo KFPRI,
optional bool bIsFirstPerson )
{ {
local string CharAttachmentMeshName; local string CharAttachmentMeshName;
local name CharAttachmentSocketName; 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; local int AttachmentSlotIndex;
local SkeletalMeshComponent AttachmentMesh;
if (KFP.WorldInfo.NetMode == NM_DedicatedServer) if (KFP.WorldInfo.NetMode == NM_DedicatedServer)
{ {
@ -281,21 +358,27 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
// Clear any previously attachments for the same slot // Clear any previously attachments for the same slot
//DetachConflictingAttachments(CurrentAttachmentMeshIndex, KFP, KFPRI); //DetachConflictingAttachments(CurrentAttachmentMeshIndex, KFP, KFPRI);
// Get a slot where this attachment could fit // Get a slot where this attachment could fit
AttachmentSlotIndex = C.GetAttachmentSlotIndex(CurrentAttachmentMeshIndex, KFP); AttachmentSlotIndex = GetAttachmentSlotIndex(C, CurrentAttachmentMeshIndex, KFP, KFPRI);
if (AttachmentSlotIndex == INDEX_NONE)
{
return;
}
// Since cosmetic attachments are optional, do not choose index 0 if none is // Since cosmetic attachments are optional, do not choose index 0 if none is
// specified unlike the the head and body meshes // specified unlike the the head and body meshes
if ( C.CosmeticVariants.length > 0 && if ( C.CosmeticVariants.Length > 0 &&
CurrentAttachmentMeshIndex < C.CosmeticVariants.length ) CurrentAttachmentMeshIndex < C.CosmeticVariants.Length )
{ {
if (KFPRI.StartLoadCosmeticContent(C, ECOSMETICTYPE_Attachment, CurrentAttachmentMeshIndex))
{
return;
}
// Cache values from character info // Cache values from character info
CharAttachmentMeshName = C.GetMeshByIndex(CurrentAttachmentMeshIndex); CharAttachmentMeshName = bIsFirstPerson ? C.Get1pMeshByIndex(CurrentAttachmentMeshIndex) : C.GetMeshByIndex(CurrentAttachmentMeshIndex);
CharAttachmentSocketName = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.SocketName; CharAttachmentSocketName = bIsFirstPerson ? C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.SocketName1p : C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.SocketName;
MaxDrawDistance = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.MaxDrawDistance; AttachmentMesh = bIsFirstPerson ? KFP.ArmsMesh : KFP.Mesh;
AttachmentLocationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeTranslation;
AttachmentRotationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeRotation;
AttachmentScaleRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeScale;
bIsSkeletalAttachment = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.bIsSkeletalAttachment;
// If previously attached and we could have changed outfits (e.g. local player UI) then re-validate // 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. // required skeletal mesh socket. Must be after body mesh DLO, but before AttachComponent.
@ -308,49 +391,127 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
} }
} }
// Set First Person Cosmetic if mesh exists for it.
if(CharAttachmentMeshName != "")
{
// Set Cosmetic Mesh
SetAttachmentMesh(C, CurrentAttachmentMeshIndex, AttachmentSlotIndex, CharAttachmentMeshName, CharAttachmentSocketName, AttachmentMesh, KFP, bIsFirstPerson);
}
else
{
// Make sure to clear out attachment if we're replacing with nothing.
if(bIsFirstPerson)
{
KFP.FirstPersonAttachments[AttachmentSlotIndex] = none;
KFP.FirstPersonAttachmentSocketNames[AttachmentSlotIndex] = '';
}
}
// Set Cosmetic Skin
SetAttachmentSkinMaterial(
C,
AttachmentSlotIndex,
C.CosmeticVariants[CurrentAttachmentMeshIndex],
CurrentAttachmentSkinIndex,
KFP,
bIsFirstPerson);
}
// Treat `CLEARED_ATTACHMENT_INDEX as special value (for client detachment)
if( CurrentAttachmentMeshIndex == `CLEARED_ATTACHMENT_INDEX )
{
C.RemoveAttachmentMeshAndSkin(AttachmentSlotIndex, KFP, KFPRI);
}
}
static final function SetAttachmentMesh(KFCharacterInfo_Human C, int CurrentAttachmentMeshIndex, int AttachmentSlotIndex, string CharAttachmentMeshName, name CharAttachmentSocketName, SkeletalMeshComponent PawnMesh, KFPawn KFP, bool bIsFirstPerson = false)
{
local StaticMeshComponent StaticAttachment;
local SkeletalMeshComponent SkeletalAttachment;
local bool bIsSkeletalAttachment;
local StaticMesh CharAttachmentStaticMesh;
local SkeletalMesh CharacterAttachmentSkelMesh;
local float MaxDrawDistance;
local SkeletalMeshSocket AttachmentSocket;
local vector AttachmentLocationRelativeToSocket, AttachmentScaleRelativeToSocket;
local rotator AttachmentRotationRelativeToSocket;
MaxDrawDistance = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.MaxDrawDistance;
AttachmentLocationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeTranslation;
AttachmentRotationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeRotation;
AttachmentScaleRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeScale;
bIsSkeletalAttachment = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.bIsSkeletalAttachment;
//`log("AttachmentLocationRelativeToSocket: x="$AttachmentLocationRelativeToSocket.x@"y="$AttachmentLocationRelativeToSocket.y@"z="$AttachmentLocationRelativeToSocket.z); //`log("AttachmentLocationRelativeToSocket: x="$AttachmentLocationRelativeToSocket.x@"y="$AttachmentLocationRelativeToSocket.y@"z="$AttachmentLocationRelativeToSocket.z);
// If it is a skeletal attachment, parent anim it to the body mesh // If it is a skeletal attachment, parent anim it to the body mesh
if (bIsSkeletalAttachment) if (bIsSkeletalAttachment)
{ {
if( SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none ) if (bIsFirstPerson && (SkeletalMeshComponent(KFP.FirstPersonAttachments[AttachmentSlotIndex]) != none))
{
SkeletalAttachment = SkeletalMeshComponent(KFP.FirstPersonAttachments[AttachmentSlotIndex]);
}
else if (!bIsFirstPerson && (SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none))
{ {
SkeletalAttachment = SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]); SkeletalAttachment = SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]);
} }
else else
{ {
SkeletalAttachment = new(KFP) class'SkeletalMeshComponent'; SkeletalAttachment = new(KFP) class'KFSkeletalMeshComponent';
if (bIsFirstPerson)
{
C.SetFirstPersonCosmeticAttachment(SkeletalAttachment);
}
SkeletalAttachment.SetActorCollision(false, false); SkeletalAttachment.SetActorCollision(false, false);
if(bIsFirstPerson)
{
KFP.FirstPersonAttachments[AttachmentSlotIndex] = SkeletalAttachment;
}
else
{
KFP.ThirdPersonAttachments[AttachmentSlotIndex] = SkeletalAttachment; KFP.ThirdPersonAttachments[AttachmentSlotIndex] = SkeletalAttachment;
} }
}
// Load and assign skeletal mesh // Load and assign skeletal mesh
CharacterAttachmentSkelMesh = SkeletalMesh(DynamicLoadObject(CharAttachmentMeshName, class'SkeletalMesh')); CharacterAttachmentSkelMesh = SkeletalMesh(DynamicLoadObject(CharAttachmentMeshName, class'SkeletalMesh'));
SkeletalAttachment.SetSkeletalMesh(CharacterAttachmentSkelMesh); SkeletalAttachment.SetSkeletalMesh(CharacterAttachmentSkelMesh);
// Parent animation and LOD transitions to body mesh // Parent animation and LOD transitions to body mesh
SkeletalAttachment.SetParentAnimComponent(KFP.Mesh); SkeletalAttachment.SetParentAnimComponent(PawnMesh);
SkeletalAttachment.SetLODParent(KFP.Mesh); SkeletalAttachment.SetLODParent(PawnMesh);
SkeletalAttachment.SetScale(C.DefaultMeshScale); SkeletalAttachment.SetScale(C.DefaultMeshScale);
SkeletalAttachment.SetCullDistance(MaxDrawDistance); SkeletalAttachment.SetCullDistance(MaxDrawDistance);
SkeletalAttachment.SetShadowParent(KFP.Mesh); SkeletalAttachment.SetShadowParent(PawnMesh);
SkeletalAttachment.SetLightingChannels(KFP.PawnLightingChannel); SkeletalAttachment.SetLightingChannels(KFP.PawnLightingChannel);
// Attach
KFP.AttachComponent(SkeletalAttachment); KFP.AttachComponent(SkeletalAttachment);
} }
// Otherwise (if static), attach to a socket on the body mesh // Otherwise (if static), attach to a socket on the body mesh
else else
{ {
if( StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none ) if (!bIsFirstPerson && (StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none))
{ {
StaticAttachment = StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]); StaticAttachment = StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]);
} }
else if (bIsFirstPerson && (StaticMeshComponent(KFP.FirstPersonAttachments[AttachmentSlotIndex]) != none))
{
StaticAttachment = StaticMeshComponent(KFP.FirstPersonAttachments[AttachmentSlotIndex]);
}
else else
{ {
StaticAttachment = new(KFP) class'StaticMeshComponent'; StaticAttachment = new(KFP) class'StaticMeshComponent';
StaticAttachment.SetActorCollision(false, false); StaticAttachment.SetActorCollision(false, false);
if(bIsFirstPerson)
{
KFP.FirstPersonAttachments[AttachmentSlotIndex] = StaticAttachment;
}
else
{
KFP.ThirdPersonAttachments[AttachmentSlotIndex] = StaticAttachment; KFP.ThirdPersonAttachments[AttachmentSlotIndex] = StaticAttachment;
} }
}
// Load and assign static mesh // Load and assign static mesh
CharAttachmentStaticMesh = StaticMesh(DynamicLoadObject(CharAttachmentMeshName, class'StaticMesh')); CharAttachmentStaticMesh = StaticMesh(DynamicLoadObject(CharAttachmentMeshName, class'StaticMesh'));
@ -363,8 +524,8 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
StaticAttachment.SetLightingChannels(KFP.PawnLightingChannel); StaticAttachment.SetLightingChannels(KFP.PawnLightingChannel);
// For static meshes, attach to given socket // For static meshes, attach to given socket
AttachmentSocket = KFP.mesh.GetSocketByName(CharAttachmentSocketName); AttachmentSocket = PawnMesh.GetSocketByName(CharAttachmentSocketName);
KFP.mesh.AttachComponent( PawnMesh.AttachComponent(
StaticAttachment, StaticAttachment,
AttachmentSocket.BoneName, AttachmentSocket.BoneName,
AttachmentSocket.RelativeLocation + AttachmentLocationRelativeToSocket, AttachmentSocket.RelativeLocation + AttachmentLocationRelativeToSocket,
@ -372,22 +533,13 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
AttachmentSocket.RelativeScale * AttachmentScaleRelativeToSocket); AttachmentSocket.RelativeScale * AttachmentScaleRelativeToSocket);
} }
// Update the pawn's attachment metadata if(bIsFirstPerson)
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); KFP.FirstPersonAttachmentSocketNames[AttachmentSlotIndex] = CharAttachmentSocketName;
}
else
{
KFP.ThirdPersonAttachmentSocketNames[AttachmentSlotIndex] = CharAttachmentSocketName;
} }
} }
@ -395,7 +547,7 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
* Removes any attachments that exist in the same socket or have overriding cases * Removes any attachments that exist in the same socket or have overriding cases
* Network: Local Player * Network: Local Player
*/ */
static final function DetachConflictingAttachments( KFCharacterInfo_Human C, byte NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI) static final function DetachConflictingAttachments( KFCharacterInfo_Human C, int NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI)
{ {
local name NewAttachmentSocketName; local name NewAttachmentSocketName;
local int i, CurrentAttachmentIdx; local int i, CurrentAttachmentIdx;
@ -409,7 +561,7 @@ static final function DetachConflictingAttachments( KFCharacterInfo_Human C, byt
NewAttachmentMeshIndex < C.CosmeticVariants.length ) NewAttachmentMeshIndex < C.CosmeticVariants.length )
{ {
// The socket that this attachment requires // The socket that this attachment requires
NewAttachmentSocketName = C.CosmeticVariants[NewAttachmentMeshIndex].SocketName; NewAttachmentSocketName = C.CosmeticVariants[NewAttachmentMeshIndex].AttachmentItem.SocketName;
for( i=0; i < `MAX_COSMETIC_ATTACHMENTS; i++ ) for( i=0; i < `MAX_COSMETIC_ATTACHMENTS; i++ )
{ {
@ -448,13 +600,14 @@ static final function SetFirstPersonArmsFromArch( KFCharacterInfo_Human C, KFPaw
local MaterialInstanceConstant M; local MaterialInstanceConstant M;
local ExtPlayerReplicationInfo EPRI; local ExtPlayerReplicationInfo EPRI;
local bool bCustom; local bool bCustom;
local int AttachmentIdx, CosmeticMeshIdx;
EPRI = ExtPlayerReplicationInfo(KFPRI);
if ( KFPRI == none ) if ( KFPRI == none )
{ {
`Warn("Does not have a KFPRI" @ C); `Warn("Does not have a KFPRI" @ C);
return; return;
} }
EPRI = ExtPlayerReplicationInfo(KFPRI);
bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false); bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false);
// First person arms mesh and skin are based on body mesh & skin. // First person arms mesh and skin are based on body mesh & skin.
@ -462,7 +615,22 @@ static final function SetFirstPersonArmsFromArch( KFCharacterInfo_Human C, KFPaw
C.SetArmsMeshAndSkin( C.SetArmsMeshAndSkin(
bCustom ? EPRI.CustomCharacter.BodyMeshIndex : KFPRI.RepCustomizationInfo.BodyMeshIndex, bCustom ? EPRI.CustomCharacter.BodyMeshIndex : KFPRI.RepCustomizationInfo.BodyMeshIndex,
bCustom ? EPRI.CustomCharacter.BodySkinIndex : KFPRI.RepCustomizationInfo.BodySkinIndex, bCustom ? EPRI.CustomCharacter.BodySkinIndex : KFPRI.RepCustomizationInfo.BodySkinIndex,
KFP); KFP,
KFPRI);
for (AttachmentIdx = 0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++)
{
CosmeticMeshIdx = bCustom ? EPRI.CustomCharacter.AttachmentMeshIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx];
if (CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX && CosmeticMeshIdx != INDEX_NONE)
{
// Attach all saved attachments to the character
SetAttachmentMeshAndSkin(
C,
CosmeticMeshIdx,
bCustom ? EPRI.CustomCharacter.AttachmentSkinIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentSkinIndices[AttachmentIdx],
KFP, KFPRI, true);
}
}
// Hack fix for a material bug on KF2 // Hack fix for a material bug on KF2
if( bCustom && KFP.ArmsMesh.SkeletalMesh!=None && KFP.ArmsMesh.GetMaterial(0)!=None ) if( bCustom && KFP.ArmsMesh.SkeletalMesh!=None && KFP.ArmsMesh.GetMaterial(0)!=None )
@ -471,3 +639,44 @@ static final function SetFirstPersonArmsFromArch( KFCharacterInfo_Human C, KFPaw
CloneMIC(M); CloneMIC(M);
} }
} }
static function int GetAttachmentSlotIndex(
KFCharacterInfo_Human C,
int CurrentAttachmentMeshIndex,
KFPawn KFP,
KFPlayerReplicationInfo KFPRI)
{
local int AttachmentIdx,CosmeticMeshIdx;
local ExtPlayerReplicationInfo EPRI;
local bool bCustom;
if( KFPRI == None )
{
`warn("GetAttachmentSlotIndex - NO KFPRI");
return INDEX_NONE;
}
EPRI = ExtPlayerReplicationInfo(KFPRI);
bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false);
// Return the next available attachment index or the index that matches this mesh
for( AttachmentIdx = 0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ )
{
CosmeticMeshIdx = bCustom ? EPRI.CustomCharacter.AttachmentMeshIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx];
if( CosmeticMeshIdx == INDEX_NONE || CosmeticMeshIdx == CurrentAttachmentMeshIndex )
{
return AttachmentIdx;
}
}
return INDEX_NONE;
}
static function bool IsAttachmentAvailable(KFCharacterInfo_Human C, const out AttachmentVariants Attachment, Pawn PreviewPawn)
{
if ( Attachment.AttachmentItem.SocketName != '' && PreviewPawn.Mesh.GetSocketByName(Attachment.AttachmentItem.SocketName) == None )
{
return false;
}
return true;
}

View File

@ -14,6 +14,7 @@ function UpdatePerk()
{ {
local int CurrentPerkLevel,CurrentPerkEXP; local int CurrentPerkLevel,CurrentPerkEXP;
local Ext_PerkBase CurrentPerk; local Ext_PerkBase CurrentPerk;
local GFxObject PerkIconObject;
if( ExPC == none || ExPC.ActivePerkManager==None || ExPC.ActivePerkManager.CurrentPerk==None ) if( ExPC == none || ExPC.ActivePerkManager==None || ExPC.ActivePerkManager.CurrentPerk==None )
return; return;
@ -26,7 +27,11 @@ function UpdatePerk()
if( ( ExLastPerkClass != CurrentPerk.Class ) || ( LastPerkLevel != CurrentPerkLevel ) ) if( ( ExLastPerkClass != CurrentPerk.Class ) || ( LastPerkLevel != CurrentPerkLevel ) )
{ {
CurPerkPath = CurrentPerk.GetPerkIconPath(CurrentPerkLevel); CurPerkPath = CurrentPerk.GetPerkIconPath(CurrentPerkLevel);
SetString("playerPerkIcon" , CurPerkPath);
PerkIconObject = CreateObject("Object");
PerkIconObject.SetString("perkIcon", CurPerkPath);
SetObject("playerPerkIcon", PerkIconObject);
SetInt("playerPerkXPPercent", CurrentPerk.GetProgressPercent() * 100.f ); SetInt("playerPerkXPPercent", CurrentPerk.GetProgressPercent() * 100.f );
if( LastPerkLevel != CurrentPerkLevel && ExLastPerkClass==CurrentPerk.Class ) if( LastPerkLevel != CurrentPerkLevel && ExLastPerkClass==CurrentPerk.Class )
{ {

View File

@ -15,6 +15,7 @@ var bool bWaitingCharList,bIsCustomChar;
function InitializeMenu( KFGFxMoviePlayer_Manager InManager ) function InitializeMenu( KFGFxMoviePlayer_Manager InManager )
{ {
super(KFGFxObject_Menu).InitializeMenu(InManager); super(KFGFxObject_Menu).InitializeMenu(InManager);
CheckForCustomizationPawn( GetPC() );
LocalizeText(); LocalizeText();
EmoteList = class'ExtEmoteList'.static.GetEmoteArray(); EmoteList = class'ExtEmoteList'.static.GetEmoteArray();
InitCharacterMenu(); InitCharacterMenu();
@ -66,9 +67,8 @@ function OnOpen()
if( PC == none ) if( PC == none )
return; return;
// @hack: moved from KFGfxMoviePlayer_Manager because this causes a crash while CheckForCustomizationPawn( PC );
// bink (e.g. KFII-25456) are playing. Don't use HandleInputAxis with Bink! (for now) :) //GetGameViewportClient().HandleInputAxis = OnAxisModified;
GetGameViewportClient().HandleInputAxis = OnAxisModified;
if ( PC.PlayerReplicationInfo.bReadyToPlay && PC.WorldInfo.GRI.bMatchHasBegun ) if ( PC.PlayerReplicationInfo.bReadyToPlay && PC.WorldInfo.GRI.bMatchHasBegun )
{ {
@ -77,6 +77,21 @@ function OnOpen()
} }
} }
/** The customization pawn won't exist if this menu was opened mid-match */
function CheckForCustomizationPawn( PlayerController PC )
{
local KFPlayerController KFPC;
if( PC.Pawn == None || (!PC.Pawn.IsAliveAndWell() && KFPawn_Customization(PC.Pawn) == None) )
{
KFPC = KFPlayerController( PC );
if( KFPC != None )
{
KFPC.SpawnMidGameCustomizationPawn();
}
}
}
function LocalizeText() function LocalizeText()
{ {
local GFxObject LocalizedObject; local GFxObject LocalizedObject;
@ -104,7 +119,7 @@ simulated function CharListRecieved()
function UpdateEmoteList() function UpdateEmoteList()
{ {
local byte ItemIndex, i; local int ItemIndex, i;
local GFxObject DataProvider, SlotObject; local GFxObject DataProvider, SlotObject;
local string TexturePath; local string TexturePath;
@ -135,7 +150,7 @@ function UpdateEmoteList()
function UpdateCharacterList() function UpdateCharacterList()
{ {
local byte i, ItemIndex; local int i, ItemIndex;
local GFxObject DataProvider, SlotObject; local GFxObject DataProvider, SlotObject;
local string TexturePath; local string TexturePath;
@ -208,7 +223,7 @@ final function string GetMenuNameStr( string ObjName )
function UpdateMeshList(string OutfitKey, string SkinKey, array<OutfitVariants> Outfits, string DataArrayString) function UpdateMeshList(string OutfitKey, string SkinKey, array<OutfitVariants> Outfits, string DataArrayString)
{ {
local byte i, ItemIndex; local int i, ItemIndex;
local GFxObject DataProvider, SlotObject; local GFxObject DataProvider, SlotObject;
local string TexturePath, OutfitName; local string TexturePath, OutfitName;
local OutfitVariants Outfit; local OutfitVariants Outfit;
@ -216,7 +231,7 @@ function UpdateMeshList(string OutfitKey, string SkinKey, array<OutfitVariants>
ItemIndex = 0; ItemIndex = 0;
DataProvider = CreateArray(); DataProvider = CreateArray();
for (i = 0; i < Outfits.length; i++) for (i = 0; i < Outfits.Length; i++)
{ {
Outfit = Outfits[i]; Outfit = Outfits[i];
@ -247,7 +262,7 @@ function UpdateMeshList(string OutfitKey, string SkinKey, array<OutfitVariants>
function SkinVariant UpdateOutfitVariants(string OutfitKey, string KeyName, out array<SkinVariant> SkinVariations, int OutfitIndex, out GFxObject MeshObject) function SkinVariant UpdateOutfitVariants(string OutfitKey, string KeyName, out array<SkinVariant> SkinVariations, int OutfitIndex, out GFxObject MeshObject)
{ {
local byte i, ItemIndex; local int i, ItemIndex;
local GFxObject DataProvider, SlotObject; local GFxObject DataProvider, SlotObject;
local SkinVariant Skin; local SkinVariant Skin;
local SkinVariant FirstSkin; local SkinVariant FirstSkin;
@ -284,41 +299,36 @@ function SkinVariant UpdateOutfitVariants(string OutfitKey, string KeyName, out
function UpdateAttachmentsList(array<AttachmentVariants> Attachments) function UpdateAttachmentsList(array<AttachmentVariants> Attachments)
{ {
local byte i, ItemIndex; local int i, ItemIndex;
local GFxObject DataProvider, SlotObject; local GFxObject DataProvider, SlotObject;
local string TexturePath; local string TexturePath;
local AttachmentVariants Variant; local AttachmentVariants Variant;
local Pawn MyPawn;
local SkinVariant FirstSkin; local SkinVariant FirstSkin;
local string AttachmentName; local string AttachmentName;
ItemIndex = 0; ItemIndex = 0;
DataProvider = CreateArray(); DataProvider = CreateArray();
MyPawn = GetPC().Pawn;
// Insert blank object // Insert blank object
SlotObject = CreateObject( "Object" ); SlotObject = CreateObject( "Object" );
SlotObject.SetString("label", class'KFGFxMenu_Gear'.Default.NoneString); SlotObject.SetString("label", class'KFGFxMenu_Gear'.default.NoneString);
SlotObject.SetString("source", "img://"$class'KFGFxMenu_Gear'.Default.ClearImagePath); SlotObject.SetString("source", "img://"$class'KFGFxMenu_Gear'.default.ClearImagePath);
SlotObject.SetInt("ItemIndex", INDEX_NONE);
SlotObject.SetBool("enabled", true); SlotObject.SetBool("enabled", true);
DataProvider.SetElementObject(ItemIndex, SlotObject); DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++; ItemIndex++;
for (i = 0; i < Attachments.length; i++) for (i = 0; i < Attachments.Length; i++)
{ {
Variant = Attachments[i]; Variant = Attachments[i];
if ( class'ExtCharacterInfo'.static.IsAttachmentAvailable(CurrentCharInfo, Variant, MyPawn) )
AttachmentName = Localize(string(Variant.AttachmentItem.Name), class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString); {
if( bIsCustomChar )
AttachmentName = GetMenuNameStr(Variant.MeshName);
if ( InStr(AttachmentName, "?INT?") != -1 )
continue;
SlotObject = CreateObject( "Object" ); SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i); SlotObject.SetInt("ItemIndex", i);
FirstSkin = UpdateCosmeticVariants( class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentSkinKey, Variant.AttachmentItem, i, SlotObject ); FirstSkin = UpdateCosmeticVariants( class'KFGFxMenu_Gear'.default.AttachmentKey, class'KFGFxMenu_Gear'.default.AttachmentSkinKey, Variant.AttachmentItem, i, SlotObject );
if( string(FirstSkin.UITexture) == "Bad" ) AttachmentName = bIsCustomChar ? GetMenuNameStr(Variant.MeshName) : Localize(string(Variant.AttachmentItem.Name), class'KFGFxMenu_Gear'.default.AttachmentKey, class'KFGFxMenu_Gear'.default.KFCharacterInfoString);
continue;
SlotObject.SetString("label", AttachmentName); SlotObject.SetString("label", AttachmentName);
SlotObject.SetBool("enabled", true); SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(FirstSkin.UITexture); TexturePath = "img://"$PathName(FirstSkin.UITexture);
@ -327,13 +337,14 @@ function UpdateAttachmentsList(array<AttachmentVariants> Attachments)
DataProvider.SetElementObject(ItemIndex, SlotObject); DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++; ItemIndex++;
} }
}
SetObject("attachmentsArray", DataProvider); SetObject("attachmentsArray", DataProvider);
} }
function SkinVariant UpdateCosmeticVariants(string OutfitKey, string KeyName, KFCharacterAttachment Attachment, int OutfitIndex, out GFxObject MeshObject) function SkinVariant UpdateCosmeticVariants(string OutfitKey, string KeyName, KFCharacterAttachment Attachment, int OutfitIndex, out GFxObject MeshObject)
{ {
local byte i, ItemIndex; local int i, ItemIndex;
local GFxObject DataProvider, SlotObject; local GFxObject DataProvider, SlotObject;
local SkinVariant Skin; local SkinVariant Skin;
local SkinVariant FirstSkin; local SkinVariant FirstSkin;
@ -372,20 +383,35 @@ function SetCurrentCharacterButtons()
{ {
local bool bCustom; local bool bCustom;
local GFxObject DataObject; local GFxObject DataObject;
local byte CharacterIndex, HeadMeshIndex, HeadSkinIndex, BodyMeshIndex, BodySkinIndex;
bCustom = ExtPRI.UsesCustomChar(); bCustom = ExtPRI.UsesCustomChar();
DataObject = CreateObject("Object"); DataObject = CreateObject("Object");
CharacterIndex = ExtPRI.RepCustomizationInfo.CharacterIndex;
HeadMeshIndex = ExtPRI.RepCustomizationInfo.HeadMeshIndex;
HeadSkinIndex = ExtPRI.RepCustomizationInfo.HeadSkinIndex;
BodyMeshIndex = ExtPRI.RepCustomizationInfo.BodyMeshIndex;
BodySkinIndex = ExtPRI.RepCustomizationInfo.BodySkinIndex;
if( bCustom )
{
CharacterIndex = ExtPRI.CustomCharacter.CharacterIndex;
HeadMeshIndex = ExtPRI.CustomCharacter.HeadMeshIndex;
HeadSkinIndex = ExtPRI.CustomCharacter.HeadSkinIndex;
BodyMeshIndex = ExtPRI.CustomCharacter.BodyMeshIndex;
BodySkinIndex = ExtPRI.CustomCharacter.BodySkinIndex;
}
DataObject.SetString( "selectedCharacter", (bIsCustomChar ? Repl(string(CurrentCharInfo.Name),"_"," ") : Localize(CharInfoPath, "CharacterName", class'KFGFxMenu_Gear'.Default.KFCharacterInfoString)) ); 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.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 ); DataObject.SetInt( "selectedCharacterIndex", CharacterIndex );
SetObject( "selectedCharacter", DataObject); SetObject( "selectedCharacter", DataObject);
//set head //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); SetGearButtons(HeadMeshIndex, HeadSkinIndex, class'KFGFxMenu_Gear'.Default.HeadMeshKey, class'KFGFxMenu_Gear'.Default.HeadSkinKey, class'KFGFxMenu_Gear'.Default.HeadFunctionKey);
//set body //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); SetGearButtons(BodyMeshIndex, BodySkinIndex, class'KFGFxMenu_Gear'.Default.BodyMeshKey, class'KFGFxMenu_Gear'.Default.BodySkinKey, class'KFGFxMenu_Gear'.Default.BodyFunctionKey);
//set attachments //set attachments
SetAttachmentButtons(class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentFunctionKey); SetAttachmentButtons(class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentFunctionKey);
@ -416,7 +442,7 @@ function SetEmoteButton()
} }
/** Update the labels for our gear buttons */ /** Update the labels for our gear buttons */
function SetGearButtons(byte MeshIndex, byte SkinIndex, string MeshKey, string SkinKey, string sectionFunctionName) function SetGearButtons(int MeshIndex, int SkinIndex, string MeshKey, string SkinKey, string sectionFunctionName)
{ {
local string SectionPath; local string SectionPath;
local string CurrentMesh; local string CurrentMesh;
@ -444,6 +470,7 @@ function SetGearButtons(byte MeshIndex, byte SkinIndex, string MeshKey, string S
SkinName = GetMenuName(CurrentCharInfo.BodyVariants[MeshIndex].SkinVariations[SkinIndex].Skin); SkinName = GetMenuName(CurrentCharInfo.BodyVariants[MeshIndex].SkinVariations[SkinIndex].Skin);
MeshName = GetMenuNameStr(CurrentCharInfo.BodyVariants[MeshIndex].MeshName); MeshName = GetMenuNameStr(CurrentCharInfo.BodyVariants[MeshIndex].MeshName);
} }
DataObject.SetString( sectionFunctionName, MeshName @"\n" @SkinName ); DataObject.SetString( sectionFunctionName, MeshName @"\n" @SkinName );
} }
else else
@ -465,9 +492,8 @@ function SetGearButtons(byte MeshIndex, byte SkinIndex, string MeshKey, string S
/** Update the labels for our currently equipped attachments */ /** Update the labels for our currently equipped attachments */
function SetAttachmentButtons(string AttachmentMeshKey, string sectionFunctionName) function SetAttachmentButtons(string AttachmentMeshKey, string sectionFunctionName)
{ {
local string FinishedString;
local GFxObject DataObject; local GFxObject DataObject;
local byte i, AttachmentIndex; local int i, AttachmentIndex;
local bool bCustom; local bool bCustom;
if( bWaitingCharList ) if( bWaitingCharList )
@ -481,16 +507,14 @@ function SetAttachmentButtons(string AttachmentMeshKey, string sectionFunctionNa
AttachmentIndex = bCustom ? ExtPRI.CustomCharacter.AttachmentMeshIndices[i] : ExtPRI.RepCustomizationInfo.AttachmentMeshIndices[i]; AttachmentIndex = bCustom ? ExtPRI.CustomCharacter.AttachmentMeshIndices[i] : ExtPRI.RepCustomizationInfo.AttachmentMeshIndices[i];
if( AttachmentIndex == `CLEARED_ATTACHMENT_INDEX ) if( AttachmentIndex == `CLEARED_ATTACHMENT_INDEX )
{ {
FinishedString $= "----"$"\n"; DataObject.SetString("selectedAttachment_"$i, "----");
} }
else else
{ {
FinishedString $= (bIsCustomChar ? GetMenuNameStr(CurrentCharInfo.CosmeticVariants[AttachmentIndex].MeshName) : Localize(string(CurrentCharInfo.CosmeticVariants[AttachmentIndex].AttachmentItem.Name), AttachmentMeshKey, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString)$"\n"); DataObject.SetString("selectedAttachment_"$i, bIsCustomChar ? GetMenuNameStr(CurrentCharInfo.CosmeticVariants[AttachmentIndex].MeshName) : Localize(string(CurrentCharInfo.CosmeticVariants[AttachmentIndex].AttachmentItem.Name), AttachmentMeshKey, class'KFGFxMenu_Gear'.default.KFCharacterInfoString));
} }
} }
DataObject.SetString( sectionFunctionName, FinishedString );
SetObject( sectionFunctionName, DataObject); SetObject( sectionFunctionName, DataObject);
} }
@ -500,7 +524,7 @@ event OnClose()
super.OnClose(); super.OnClose();
GetGameViewportClient().HandleInputAxis = none; //GetGameViewportClient().HandleInputAxis = none;
if ( class'WorldInfo'.static.IsMenuLevel() ) if ( class'WorldInfo'.static.IsMenuLevel() )
{ {
@ -531,7 +555,7 @@ event bool OnAxisModified( int ControllerId, name Key, float Delta, float DeltaT
// ActionScript Callbacks // ActionScript Callbacks
//============================================================== //==============================================================
function Callback_Emote(byte Index) function Callback_Emote(int Index)
{ {
local KFPlayerController KFPC; local KFPlayerController KFPC;
@ -588,13 +612,13 @@ function Callback_HeadCamera()
KFPlayerCamera( GetPC().PlayerCamera ).CustomizationCam.SetBodyView( 1 ); KFPlayerCamera( GetPC().PlayerCamera ).CustomizationCam.SetBodyView( 1 );
} }
function Callback_Character(byte Index) function Callback_Character(int Index)
{ {
ExtPRI.ChangeCharacter(Index,!ExtPRI.UsesCustomChar()); ExtPRI.ChangeCharacter(Index,!ExtPRI.UsesCustomChar());
UpdateGear(); UpdateGear();
} }
function Callback_Head( byte MeshIndex, byte SkinIndex ) function Callback_Head( int MeshIndex, int SkinIndex )
{ {
if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server. if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server.
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true); ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
@ -602,7 +626,7 @@ function Callback_Head( byte MeshIndex, byte SkinIndex )
SetGearButtons(MeshIndex, SkinIndex, class'KFGFxMenu_Gear'.Default.HeadMeshKey, class'KFGFxMenu_Gear'.Default.HeadSkinKey, class'KFGFxMenu_Gear'.Default.HeadFunctionKey); 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 ) function Callback_Body( int MeshIndex, int SkinIndex )
{ {
if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server. if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server.
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true); ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
@ -617,7 +641,7 @@ function Callback_Body( byte MeshIndex, byte SkinIndex )
SetGearButtons(MeshIndex, SkinIndex, class'KFGFxMenu_Gear'.Default.BodyMeshKey, class'KFGFxMenu_Gear'.Default.BodySkinKey, class'KFGFxMenu_Gear'.Default.BodyFunctionKey); 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 ) function Callback_Attachment( int MeshIndex, int SkinIndex )
{ {
local int SlotIndex; local int SlotIndex;
local KFPawn KFP; local KFPawn KFP;
@ -626,14 +650,19 @@ function Callback_Attachment( byte MeshIndex, byte SkinIndex )
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true); ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
KFP = KFPawn(GetPC().Pawn); KFP = KFPawn(GetPC().Pawn);
if( KFP!=None ) if( KFP!=None && ExtPRI!=None )
{ {
if( MeshIndex==`CLEARED_ATTACHMENT_INDEX ) if( MeshIndex==`CLEARED_ATTACHMENT_INDEX )
ExtPRI.RemoveAttachments(); ExtPRI.RemoveAttachments();
else else
{ {
class'ExtCharacterInfo'.Static.DetachConflictingAttachments(CurrentCharInfo, MeshIndex, KFP, ExtPRI); class'ExtCharacterInfo'.Static.DetachConflictingAttachments(CurrentCharInfo, MeshIndex, KFP, ExtPRI);
SlotIndex = CurrentCharInfo.GetAttachmentSlotIndex(MeshIndex, KFP); SlotIndex = class'ExtCharacterInfo'.Static.GetAttachmentSlotIndex(CurrentCharInfo, MeshIndex, KFP, ExtPRI);
if(SlotIndex == INDEX_NONE)
{
return;
}
ExtPRI.UpdateCustomization(CO_Attachment, MeshIndex, SkinIndex, SlotIndex); ExtPRI.UpdateCustomization(CO_Attachment, MeshIndex, SkinIndex, SlotIndex);
} }

View File

@ -103,8 +103,8 @@ defaultproperties
WidgetBindings.Add((WidgetName="PlayerBackpackWidget",WidgetClass=class'ExtHUD_PlayerBackpack')) WidgetBindings.Add((WidgetName="PlayerBackpackWidget",WidgetClass=class'ExtHUD_PlayerBackpack'))
WidgetBindings.Remove((WidgetName="WaveInfoContainer",WidgetClass=class'KFGFxHUD_WaveInfo')) WidgetBindings.Remove((WidgetName="WaveInfoContainer",WidgetClass=class'KFGFxHUD_WaveInfo'))
WidgetBindings.Add((WidgetName="WaveInfoContainer",WidgetClass=class'ExtHUD_WaveInfo')) WidgetBindings.Add((WidgetName="WaveInfoContainer",WidgetClass=class'ExtHUD_WaveInfo'))
WidgetBindings.Remove((WidgetName="bossHealthBar", WidgetClass=class'KFGFxWidget_BossHealthBar')) //WidgetBindings.Remove((WidgetName="bossHealthBar", WidgetClass=class'KFGFxWidget_BossHealthBar'))
WidgetBindings.Add((WidgetName="bossHealthBar", WidgetClass=class'ExtWidget_BossHealthBar')) //WidgetBindings.Add((WidgetName="bossHealthBar", WidgetClass=class'ExtWidget_BossHealthBar'))
WidgetBindings.Remove((WidgetName="WeaponSelectContainer",WidgetClass=class'KFGFxHUD_WeaponSelectWidget')) WidgetBindings.Remove((WidgetName="WeaponSelectContainer",WidgetClass=class'KFGFxHUD_WeaponSelectWidget'))
WidgetBindings.Add((WidgetName="WeaponSelectContainer",WidgetClass=class'ExtHUD_WeaponSelectWidget')) WidgetBindings.Add((WidgetName="WeaponSelectContainer",WidgetClass=class'ExtHUD_WeaponSelectWidget'))
} }

View File

@ -144,7 +144,7 @@ reliable client event ReceiveLocalizedMessage( class<LocalMessage> Message, opti
Super.ReceiveLocalizedMessage(Message,Switch,RelatedPRI_1,RelatedPRI_2,OptionalObject); Super.ReceiveLocalizedMessage(Message,Switch,RelatedPRI_1,RelatedPRI_2,OptionalObject);
} }
function AddZedKill( class<KFPawn_Monster> MonsterClass, byte Difficulty, class<DamageType> DT ) function AddZedKill( class<KFPawn_Monster> MonsterClass, byte Difficulty, class<DamageType> DT, bool bKiller )
{ {
// Stats. // Stats.
if( ActivePerkManager!=None ) if( ActivePerkManager!=None )
@ -603,7 +603,7 @@ simulated function CancelConnection()
else class'Engine'.Static.GetEngine().GameViewport.ConsoleCommand("Disconnect"); else class'Engine'.Static.GetEngine().GameViewport.ConsoleCommand("Disconnect");
} }
function NotifyLevelUp(class<KFPerk> PerkClass, byte PerkLevel); function NotifyLevelUp(class<KFPerk> PerkClass, byte PerkLevel, byte NewPrestigeLevel);
function ShowBossNameplate( KFInterface_MonsterBoss KFBoss, optional string PlayerName) function ShowBossNameplate( KFInterface_MonsterBoss KFBoss, optional string PlayerName)
{ {
@ -1167,6 +1167,16 @@ state Dead
} }
} }
exec function RequestSwitchTeam()
{
ConsoleCommand("disconnect");
}
exec function SwitchTeam()
{
ConsoleCommand("disconnect");
}
defaultproperties defaultproperties
{ {
InputClass=Class'ExtPlayerInput' InputClass=Class'ExtPlayerInput'

View File

@ -12,10 +12,9 @@ struct FMyCustomChar // Now without constant.
structdefaultproperties structdefaultproperties
{ {
CharacterIndex=255 AttachmentMeshIndices[0]=`CLEARED_ATTACHMENT_INDEX
AttachmentMeshIndices[0]=255 AttachmentMeshIndices[1]=`CLEARED_ATTACHMENT_INDEX
AttachmentMeshIndices[1]=255 AttachmentMeshIndices[2]=`CLEARED_ATTACHMENT_INDEX
AttachmentMeshIndices[2]=255
} }
}; };
@ -658,7 +657,7 @@ final function SaveCustomCharacter( ExtSaveDataBase Data )
c = 0; c = 0;
for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i ) for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i )
{ {
if( CustomCharacter.AttachmentMeshIndices[i]!=255 ) if( CustomCharacter.AttachmentMeshIndices[i]!=`CLEARED_ATTACHMENT_INDEX )
++c; ++c;
} }
@ -668,7 +667,7 @@ final function SaveCustomCharacter( ExtSaveDataBase Data )
// Write attachments. // Write attachments.
for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i ) for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i )
{ {
if( CustomCharacter.AttachmentMeshIndices[i]!=255 ) if( CustomCharacter.AttachmentMeshIndices[i]!=`CLEARED_ATTACHMENT_INDEX )
{ {
Data.SaveInt(i); Data.SaveInt(i);
Data.SaveInt(CustomCharacter.AttachmentMeshIndices[i]); Data.SaveInt(CustomCharacter.AttachmentMeshIndices[i]);
@ -748,6 +747,16 @@ static final function DummySaveChar( ExtSaveDataBase Data )
Data.SaveStr(""); Data.SaveStr("");
} }
simulated function Texture2D GetCurrentIconToDisplay()
{
if(CurrentVoiceCommsRequest == VCT_NONE && ECurrentPerk != none)
{
return ECurrentPerk.default.PerkIcon;
}
return class'KFLocalMessage_VoiceComms'.default.VoiceCommsIcons[CurrentVoiceCommsRequest];
}
// Set admin levels without having to hard-reference to this mod. // Set admin levels without having to hard-reference to this mod.
event BeginState(Name N) event BeginState(Name N)
{ {

View File

@ -21,7 +21,7 @@ function GFxObject RefreshSlot( int SlotIndex, KFPlayerReplicationInfo KFPRI )
local bool bIsLeader; local bool bIsLeader;
local bool bIsMyPlayer; local bool bIsMyPlayer;
local ExtPlayerController EPC; local ExtPlayerController EPC;
local GFxObject PlayerInfoObject; local GFxObject PlayerInfoObject, PerkIconObject;
local ExtPlayerReplicationInfo EPRI; local ExtPlayerReplicationInfo EPRI;
PlayerInfoObject = CreateObject("Object"); PlayerInfoObject = CreateObject("Object");
@ -42,8 +42,11 @@ function GFxObject RefreshSlot( int SlotIndex, KFPlayerReplicationInfo KFPRI )
PlayerInfoObject.SetBool("myPlayer", bIsMyPlayer); PlayerInfoObject.SetBool("myPlayer", bIsMyPlayer);
if( ExtMemberSlots[SlotIndex].PerkClass != none ) if( ExtMemberSlots[SlotIndex].PerkClass != none )
{ {
PerkIconObject = CreateObject("Object");
PerkIconObject.SetString("perkIcon", ExtMemberSlots[SlotIndex].PerkClass.static.GetPerkIconPath(EPRI.ECurrentPerkLevel));
PlayerInfoObject.SetObject("perkImageSource", PerkIconObject);
PlayerInfoObject.SetString("perkLevel", string(EPRI.ECurrentPerkLevel)); PlayerInfoObject.SetString("perkLevel", string(EPRI.ECurrentPerkLevel));
PlayerInfoObject.SetString("perkIconPath", ExtMemberSlots[SlotIndex].PerkClass.static.GetPerkIconPath(EPRI.ECurrentPerkLevel));
} }
if( !bIsMyPlayer ) if( !bIsMyPlayer )
{ {
@ -76,5 +79,4 @@ function GFxObject RefreshSlot( int SlotIndex, KFPlayerReplicationInfo KFPRI )
DefaultProperties DefaultProperties
{ {
PlayerSlots=12
} }

View File

@ -105,7 +105,7 @@ simulated final function bool IsWeaponOnPerk( KFWeapon W )
simulated static function string GetPerkIconPath( int Level ) simulated static function string GetPerkIconPath( int Level )
{ {
return "img://"$PathName(Default.PerkIcon); return "img://"$PathName(default.PerkIcon);
} }
simulated function PostBeginPlay() simulated function PostBeginPlay()

View File

@ -446,26 +446,47 @@ final function RenderProgress()
function DrawHUD() function DrawHUD()
{ {
local KFPawn KFPH; local KFPawn_Human KFPH;
local KFPawn_Human H; local KFPawn_Scripted KFPS;
local vector ViewLocation, ViewVector, PlayerPartyInfoLocation, PawnLocation;
local rotator ViewRotation;
local array<PlayerReplicationInfo> VisibleHumanPlayers;
local array<sHiddenHumanPawnInfo> HiddenHumanPlayers;
local float ThisDot,DotScale; local float ThisDot,DotScale;
local vector TargetLocation;
local Actor LocActor;
local KFPawn_Monster M; local KFPawn_Monster M;
local vector V; local vector V;
local bool bSpec; local bool bSpec;
local array<PlayerReplicationInfo> VisibleHumanPlayers;
local array<sHiddenHumanPawnInfo> HiddenHumanPlayers;
local vector ViewLocation,PawnLocation;
local rotator ViewRotation;
Super(HUD).DrawHUD(); // Draw weapon HUD underneath everything else
if( KFPlayerOwner != none && KFPlayerOwner.Pawn != none && KFPlayerOwner.Pawn.Weapon != none )
{
KFPlayerOwner.Pawn.Weapon.DrawHUD( self, Canvas );
}
super.DrawHUD();
// Cache GRI
if( KFGRI == none )
{
KFGRI = KFGameReplicationInfo( WorldInfo.GRI );
}
// Don't draw canvas HUD in cinematic mode
if( KFPlayerOwner != none && KFPlayerOwner.bCinematicMode )
{
return;
}
LocActor = KFPlayerOwner.ViewTarget != none ? KFPlayerOwner.ViewTarget : KFPlayerOwner;
// Draw the crosshair for casual mode // Draw the crosshair for casual mode
if( bDrawCrosshair || bForceDrawCrosshair || (KFPlayerOwner != none && KFPlayerOwner.GetTeamNum() == 255) ) if( KFPlayerOwner != none && (bDrawCrosshair || bForceDrawCrosshair || KFPlayerOwner.GetTeamNum() == 255) )
{ {
if( KFPlayerOwner != none && !KFPlayerOwner.bCinematicMode )
DrawCrosshair(); DrawCrosshair();
} }
// Friendly player status
bSpec = (PlayerOwner.PlayerReplicationInfo!=None && PlayerOwner.PlayerReplicationInfo.bOnlySpectator); bSpec = (PlayerOwner.PlayerReplicationInfo!=None && PlayerOwner.PlayerReplicationInfo.bOnlySpectator);
if( bSpec || PlayerOwner.GetTeamNum()==0 ) if( bSpec || PlayerOwner.GetTeamNum()==0 )
{ {
@ -476,67 +497,80 @@ function DrawHUD()
{ {
KFPlayerOwner.GetPlayerViewPoint( ViewLocation, ViewRotation ); KFPlayerOwner.GetPlayerViewPoint( ViewLocation, ViewRotation );
} }
ViewVector = vector(ViewRotation);
Canvas.EnableStencilTest(true); Canvas.EnableStencilTest(true);
foreach WorldInfo.AllPawns(class'KFPawn', KFPH) foreach WorldInfo.AllPawns( class'KFPawn_Human', KFPH )
{ {
if( KFPH == None ) if( KFPH.IsAliveAndWell() && KFPH != KFPlayerOwner.Pawn && KFPH.Mesh.SkeletalMesh != none && KFPH.Mesh.bAnimTreeInitialised )
continue;
H = KFPawn_Human(KFPH);
if( KFPH.PlayerReplicationInfo!=None && KFPH.PlayerReplicationInfo.Team!=None && KFPH.PlayerReplicationInfo.Team.TeamIndex==0 )
{ {
V = KFPH.Location + KFPH.MTO_PhysSmoothOffset + KFPH.CylinderComponent.CollisionHeight * vect(0,0,1); PlayerPartyInfoLocation = KFPH.Mesh.GetPosition() + ( KFPH.CylinderComponent.CollisionHeight * vect(0,0,1) );
ThisDot = Normal(V - PLCameraLoc) dot Normal(PLCameraDir); if(`TimeSince(KFPH.Mesh.LastRenderTime) < 0.2f && Normal(PlayerPartyInfoLocation - ViewLocation) dot ViewVector > 0.f )
if( KFPH.IsAliveAndWell() && KFPH != PlayerOwner.Pawn)
{ {
if((WorldInfo.TimeSeconds - KFPH.Mesh.LastRenderTime) < 0.4f && (ThisDot > 0 && ThisDot < 1.0) ) if( DrawFriendlyHumanPlayerInfo(KFPH) )
{ {
if( H!=None ) VisibleHumanPlayers.AddItem( KFPH.PlayerReplicationInfo );
{
DrawFriendlyHUD(H);
VisibleHumanPlayers.AddItem( H.PlayerReplicationInfo );
} }
else DrawMonsterHUD(KFPH); else
}
else if( H != None )
{ {
HiddenHumanPlayers.Insert( 0, 1 ); HiddenHumanPlayers.Insert( 0, 1 );
HiddenHumanPlayers[0].HumanPawn = H; HiddenHumanPlayers[0].HumanPawn = KFPH;
HiddenHumanPlayers[0].HumanPRI = H.PlayerReplicationInfo; HiddenHumanPlayers[0].HumanPRI = KFPH.PlayerReplicationInfo;
} }
} }
else
{
HiddenHumanPlayers.Insert( 0, 1 );
HiddenHumanPlayers[0].HumanPawn = KFPH;
HiddenHumanPlayers[0].HumanPRI = KFPH.PlayerReplicationInfo;
}
} }
} }
foreach WorldInfo.AllPawns(class'KFPawn_Scripted', KFPS)
{
if (KFPS.ShouldShowOnHUD())
{
PlayerPartyInfoLocation = KFPS.Mesh.GetPosition() + (KFPS.CylinderComponent.CollisionHeight * vect(0,0,1));
DrawScriptedPawnInfo(KFPS, Normal(PlayerPartyInfoLocation - ViewLocation) dot ViewVector, `TimeSince(KFPS.Mesh.LastRenderTime) < 0.2f);
}
}
if( !KFGRI.bHidePawnIcons )
{
// Draw hidden players // Draw hidden players
CheckAndDrawHiddenPlayerIcons( VisibleHumanPlayers, HiddenHumanPlayers ); CheckAndDrawHiddenPlayerIcons( VisibleHumanPlayers, HiddenHumanPlayers );
// Draw last remaining zeds // Draw last remaining zeds
CheckAndDrawRemainingZedIcons(); CheckAndDrawRemainingZedIcons();
Canvas.EnableStencilTest(false); //Draw our current objective location
if(KFGRI.CurrentObjective != none && KFGRI.ObjectiveInterface != none)
{
KFGRI.ObjectiveInterface.DrawHUD(self, Canvas);
if( bSpec ) TargetLocation = KFGRI.ObjectiveInterface.GetIconLocation();
ThisDot = Normal((TargetLocation + (class'KFPawn_Human'.default.CylinderComponent.CollisionHeight * vect(0, 0, 1))) - ViewLocation) dot ViewVector;
if (ThisDot > 0 &&
KFGRI.ObjectiveInterface.ShouldShowObjectiveHUD() &&
(!KFGRI.ObjectiveInterFace.HasObjectiveDrawDistance() || VSizeSq(TargetLocation - LocActor.Location) < MaxDrawDistanceObjective))
{ {
// Draw zed health bars. DrawObjectiveHUD();
foreach WorldInfo.AllPawns(class'KFPawn_Monster', M)
{
ThisDot = (PLCameraDir Dot (M.Location + M.CylinderComponent.CollisionHeight * vect(0,0,1))) - PLCameraDot;
if( ThisDot>0 && ThisDot<8000.f && M.IsAliveAndWell() && M.PlayerReplicationInfo!=None && M!=PlayerOwner.Pawn && (WorldInfo.TimeSeconds - M.Mesh.LastRenderTime) < 0.4f )
DrawFriendlyHUDZ(M);
} }
} }
} }
Canvas.EnableStencilTest(false);
}
} }
else if( KFPawn_Monster(PlayerOwner.Pawn)!=None ) else if( KFPawn_Monster(PlayerOwner.Pawn)!=None )
{ {
// Draw human health auras. // Draw human health auras.
DotScale = Canvas.ClipX*0.2f; DotScale = Canvas.ClipX*0.2f;
foreach WorldInfo.AllPawns(class'KFPawn_Human', H) foreach WorldInfo.AllPawns(class'KFPawn_Human', KFPH)
{ {
PawnLocation = H.Location; PawnLocation = KFPH.Location;
if( IsZero( PawnLocation ) ) if( IsZero( PawnLocation ) )
{ {
@ -544,12 +578,12 @@ function DrawHUD()
} }
ThisDot = (PLCameraDir Dot PawnLocation) - PLCameraDot; ThisDot = (PLCameraDir Dot PawnLocation) - PLCameraDot;
if( H.IsAliveAndWell() && ThisDot>0.f && ThisDot<10000.f ) if( KFPH.IsAliveAndWell() && ThisDot>0.f && ThisDot<10000.f )
{ {
V = Canvas.Project(PawnLocation); V = Canvas.Project(PawnLocation);
if( V.X<-100 || V.X>(Canvas.SizeX+100) || V.Y<-100 || V.Y>(Canvas.SizeY+100) ) if( V.X<-100 || V.X>(Canvas.SizeX+100) || V.Y<-100 || V.Y>(Canvas.SizeY+100) )
continue; continue;
Canvas.DrawColor = GetHPColorScale(H); Canvas.DrawColor = GetHPColorScale(KFPH);
if( PlayerOwner.FastTrace(PawnLocation,PLCameraLoc) ) if( PlayerOwner.FastTrace(PawnLocation,PLCameraLoc) )
ThisDot*=1.75f; ThisDot*=1.75f;
ThisDot = (DotScale/ThisDot)*350.f; ThisDot = (DotScale/ThisDot)*350.f;
@ -560,6 +594,7 @@ function DrawHUD()
if( !class'ExtPlayerController'.Default.bHideNameBeacons ) if( !class'ExtPlayerController'.Default.bHideNameBeacons )
{ {
Canvas.EnableStencilTest(true);
// Draw zed health bars. // Draw zed health bars.
foreach WorldInfo.AllPawns(class'KFPawn_Monster', M) foreach WorldInfo.AllPawns(class'KFPawn_Monster', M)
{ {
@ -567,52 +602,9 @@ function DrawHUD()
if( ThisDot>0 && ThisDot<8000.f && M.IsAliveAndWell() && M.PlayerReplicationInfo!=None && M!=PlayerOwner.Pawn && (WorldInfo.TimeSeconds - M.Mesh.LastRenderTime) < 0.4f ) if( ThisDot>0 && ThisDot<8000.f && M.IsAliveAndWell() && M.PlayerReplicationInfo!=None && M!=PlayerOwner.Pawn && (WorldInfo.TimeSeconds - M.Mesh.LastRenderTime) < 0.4f )
DrawFriendlyHUDZ(M); DrawFriendlyHUDZ(M);
} }
Canvas.EnableStencilTest(false);
} }
} }
Canvas.Font = GetFontSizeIndex(0);
DrawActorOverlays(PLCameraLoc, PLCameraRot);
}
function DrawHiddenHumanPlayerIcon( PlayerReplicationInfo PRI, vector IconWorldLocation )
{
local vector ScreenPos;
local float IconSizeMult;
local KFPlayerReplicationInfo KFPRI;
local Texture2D PlayerIcon;
local Color PerkColor;
local ExtPlayerReplicationInfo ExtPRI;
local Texture2D HumanIcon;
KFPRI = KFPlayerReplicationInfo(PRI);
if( KFPRI == None )
return;
// Project world pos to canvas
ScreenPos = Canvas.Project( IconWorldLocation + vect(0,0,2.2f) * class'KFPAwn_Human'.default.CylinderComponent.CollisionHeight );
// Fudge by icon size
IconSizeMult = PlayerStatusIconSize * FriendlyHudScale * 0.5f;
ScreenPos.X -= IconSizeMult;
ScreenPos.Y -= IconSizeMult;
if( ScreenPos.X < 0 || ScreenPos.X > Canvas.SizeX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.SizeY )
{
return;
}
ExtPRI = ExtPlayerReplicationInfo(KFPRI);
if( ExtPRI == None )
return;
HumanIcon = ExtPRI.ECurrentPerk != None ? ExtPRI.ECurrentPerk.Default.PerkIcon : GenericHumanIconTexture;
PlayerIcon = PlayerOwner.GetTeamNum() == 0 ? HumanIcon : GenericHumanIconTexture;
PerkColor = ExtPRI.HUDPerkColor;
// Draw human icon
Canvas.SetDrawColor( PerkColor.R, PerkColor.G, PerkColor.B, PerkColor.A );
Canvas.SetPos( ScreenPos.X, ScreenPos.Y );
Canvas.DrawTile( PlayerIcon, PlayerStatusIconSize * FriendlyHudScale, PlayerStatusIconSize * FriendlyHudScale, 0, 0, 256, 256 );
} }
simulated static final function color GetHPColorScale( Pawn P ) simulated static final function color GetHPColorScale( Pawn P )
@ -642,8 +634,10 @@ simulated function DrawFriendlyHUDZ( KFPawn_Monster KFPH )
local vector ScreenPos, TargetLocation; local vector ScreenPos, TargetLocation;
local FontRenderInfo MyFontRenderInfo; local FontRenderInfo MyFontRenderInfo;
local float FontScale; local float FontScale;
local byte FadeAlpha;
MyFontRenderInfo = Canvas.CreateFontRenderInfo( true ); MyFontRenderInfo = Canvas.CreateFontRenderInfo( true );
FadeAlpha = DrawToDistance(KFPH);
BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale; BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale;
BarHeight = FMin(8.f * (float(Canvas.SizeX) / 1024.f), 8.f) * FriendlyHudScale; BarHeight = FMin(8.f * (float(Canvas.SizeX) / 1024.f), 8.f) * FriendlyHudScale;
@ -656,16 +650,19 @@ simulated function DrawFriendlyHUDZ( KFPawn_Monster KFPH )
//Draw health bar //Draw health bar
Percentage = float(KFPH.Health) / float(KFPH.HealthMax); Percentage = float(KFPH.Health) / float(KFPH.HealthMax);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor); DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor, FadeAlpha);
//Draw player name (Top) //Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale; FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont(); Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
Canvas.SetDrawColorStruct(DrawToDistance(KFPH, PlayerBarTextColor));
Canvas.DrawColor = PlayerBarTextColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 2); Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 2);
Canvas.DrawText( KFPH.PlayerReplicationInfo.PlayerName,,FontScale,FontScale, MyFontRenderInfo ); Canvas.DrawText( KFPH.PlayerReplicationInfo.PlayerName,,FontScale,FontScale, MyFontRenderInfo );
} }
simulated function DrawFriendlyHUD( KFPawn_Human KFPH ) simulated function bool DrawFriendlyHumanPlayerInfo( KFPawn_Human KFPH )
{ {
local float Percentage; local float Percentage;
local float BarHeight, BarLength; local float BarHeight, BarLength;
@ -673,91 +670,122 @@ simulated function DrawFriendlyHUD( KFPawn_Human KFPH )
local ExtPlayerReplicationInfo KFPRI; local ExtPlayerReplicationInfo KFPRI;
local FontRenderInfo MyFontRenderInfo; local FontRenderInfo MyFontRenderInfo;
local float FontScale; local float FontScale;
local float ResModifier;
local float PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, PerkIconSize;
local color CurrentArmorColor, CurrentHealthColor, TextColor;
local string S; local string S;
local byte FadeAlpha;
ResModifier = WorldInfo.static.GetResolutionBasedHUDScale() * FriendlyHudScale;
KFPRI = ExtPlayerReplicationInfo(KFPH.PlayerReplicationInfo); KFPRI = ExtPlayerReplicationInfo(KFPH.PlayerReplicationInfo);
if( KFPRI == none ) if( KFPRI == none )
return; {
return false;
}
FadeAlpha = DrawToDistance(KFPH);
MyFontRenderInfo = Canvas.CreateFontRenderInfo( true ); MyFontRenderInfo = Canvas.CreateFontRenderInfo( true );
BarLength = FMin(PlayerStatusBarLengthMax * (Canvas.ClipX / 1024.f), PlayerStatusBarLengthMax) * ResModifier;
BarHeight = FMin(8.f * (Canvas.ClipX / 1024.f), 8.f) * ResModifier;
BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale; TargetLocation = KFPH.Mesh.GetPosition() + ( KFPH.CylinderComponent.CollisionHeight * vect(0,0,2.5f) );
BarHeight = FMin(8.f * (float(Canvas.SizeX) / 1024.f), 8.f) * FriendlyHudScale;
TargetLocation = KFPH.Location + vect(0,0,1) * KFPH.GetCollisionHeight() * 1.2;
ScreenPos = Canvas.Project( TargetLocation ); ScreenPos = Canvas.Project( TargetLocation );
if( ScreenPos.X < 0 || ScreenPos.X > Canvas.SizeX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.SizeY ) if( ScreenPos.X < 0 || ScreenPos.X > Canvas.ClipX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.ClipY )
return; {
return false;
//Draw health bar }
Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax),1.f);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor, true);
//Draw armor bar
Percentage = FMin(float(KFPH.Armor) / float(KFPH.MaxArmor),1.f);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight, ArmorColor);
//Draw player name (Top) //Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale; FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont(); Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
S = KFPRI.GetHumanReadableName();
// drop shadow for player name text
S = KFPRI.PlayerName;
if( KFPRI.bBot ) if( KFPRI.bBot )
{ {
S = S$" (Bot)"; S = S$" (Bot)";
Canvas.DrawColor = KFPRI.HUDPerkColor; TextColor = KFPRI.HUDPerkColor;
} }
else if( KFPRI.ShowAdminName() ) // Admin info. else if( KFPRI.ShowAdminName() ) // Admin info.
{ {
S = S$" ("$KFPRI.GetAdminNameAbr()$")"; S = S$" ("$KFPRI.GetAdminNameAbr()$")";
Canvas.DrawColor = KFPRI.GetAdminColorC(); TextColor = KFPRI.GetAdminColorC();
} }
else Canvas.DrawColor = WhiteColor; else TextColor = PlayerBarTextColor;
if( bMeAdmin && KFPRI.FixedData>0 ) if( bMeAdmin && KFPRI.FixedData>0 )
{ {
Canvas.SetDrawColor(255,0,0,255); TextColor = MakeColor(255,0,0,255);
S $= " -"$KFPRI.GetDesc(); S @= "-"$KFPRI.GetDesc();
} }
Canvas.DrawColor = DrawToDistance(KFPH, Canvas.DrawColor);
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 3); TextColor.A = FadeAlpha;
Canvas.DrawColor = PlayerBarShadowColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f) + 1, ScreenPos.Y + 8);
Canvas.DrawText(S, , FontScale, FontScale, MyFontRenderInfo); Canvas.DrawText(S, , FontScale, FontScale, MyFontRenderInfo);
if( KFPRI.ECurrentPerk!=none ) Canvas.DrawColor = TextColor;
{ Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + 7);
//draw perk icon Canvas.DrawText(S, , FontScale, FontScale, MyFontRenderInfo);
Canvas.DrawColor = DrawToDistance(KFPH, KFPRI.HUDPerkColor);
Canvas.SetPos(ScreenPos.X - (BarLength * 0.75), ScreenPos.Y - BarHeight * 2);
Canvas.DrawRect(PlayerStatusIconSize*FriendlyHudScale,PlayerStatusIconSize*FriendlyHudScale,KFPRI.ECurrentPerk.default.PerkIcon);
//Draw perk level and name text //Draw armor bar
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y + BarHeight); Percentage = FMin(float(KFPH.Armor) / float(KFPH.MaxArmor), 100);
CurrentArmorColor = ClassicPlayerInfo ? ClassicArmorColor : ArmorColor;
CurrentArmorColor.A = FadeAlpha;
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight + (36 * FontScale * ResModifier), CurrentArmorColor, FadeAlpha);
//Draw health bar
Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax), 100);
CurrentHealthColor = ClassicPlayerInfo ? ClassicHealthColor : HealthColor;
CurrentHealthColor.A = FadeAlpha;
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight * 2 + (36 * FontScale * ResModifier), CurrentHealthColor, FadeAlpha, true);
if( KFPRI.ECurrentPerk == None )
{
return false;
}
// drop shadow for perk name text
Canvas.DrawColor = PlayerBarShadowColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f) + 1, ScreenPos.Y + BarHeight * 3 + (36 * FontScale * ResModifier) + 1);
Canvas.DrawText(KFPRI.GetPerkLevelStr()@KFPRI.ECurrentPerk.default.PerkName, , FontScale, FontScale, MyFontRenderInfo); Canvas.DrawText(KFPRI.GetPerkLevelStr()@KFPRI.ECurrentPerk.default.PerkName, , FontScale, FontScale, MyFontRenderInfo);
if( KFPRI.HasSupplier!=None ) //Draw perk level and name text
{ Canvas.DrawColor = PlayerBarTextColor;
Canvas.DrawColor = DrawToDistance(KFPH, (KFPlayerOwner.Pawn==None || KFPRI.CanUseSupply(KFPlayerOwner.Pawn)) ? SupplierUsableColor : SupplierActiveColor); Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos( ScreenPos.X + BarLength * 0.5f, ScreenPos.Y - BarHeight * 2 ); Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight * 3 + (36 * FontScale * ResModifier));
Canvas.DrawRect( PlayerStatusIconSize*FriendlyHudScale, PlayerStatusIconSize*FriendlyHudScale, KFPRI.HasSupplier.Default.SupplyIcon); Canvas.DrawText(KFPRI.GetPerkLevelStr()@KFPRI.ECurrentPerk.default.PerkName, , FontScale, FontScale, MyFontRenderInfo);
}
}
else if( KFPRI.bBot && KFPRI.CurrentPerkClass!=none )
{
//draw perk icon
Canvas.SetPos(ScreenPos.X - (BarLength * 0.75), ScreenPos.Y - BarHeight * 2);
Canvas.DrawRect(PlayerStatusIconSize*FriendlyHudScale,PlayerStatusIconSize*FriendlyHudScale,KFPRI.CurrentPerkClass.default.PerkIcon);
//Draw name text // drop shadow for perk icon
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y + BarHeight); Canvas.DrawColor = PlayerBarShadowColor;
Canvas.DrawText( KFPRI.CurrentPerkClass.default.PerkName,,FontScale,FontScale, MyFontRenderInfo ); Canvas.DrawColor.A = FadeAlpha;
PerkIconSize = PlayerStatusIconSize * ResModifier;
PerkIconPosX = ScreenPos.X - (BarLength * 0.5f) - PerkIconSize + 1;
PerkIconPosY = ScreenPos.Y + (36 * FontScale * ResModifier) + 1;
SupplyIconPosX = ScreenPos.X + (BarLength * 0.5f) + 1;
SupplyIconPosY = PerkIconPosY + 4 * ResModifier;
DrawPerkIcons(KFPH, PerkIconSize, PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, true);
//draw perk icon
Canvas.DrawColor = PlayerBarIconColor;
Canvas.DrawColor.A = FadeAlpha;
PerkIconPosX = ScreenPos.X - (BarLength * 0.5f) - PerkIconSize;
PerkIconPosY = ScreenPos.Y + (36 * FontScale * ResModifier);
SupplyIconPosX = ScreenPos.X + (BarLength * 0.5f);
SupplyIconPosY = PerkIconPosY + 4 * ResModifier;
DrawPerkIcons(KFPH, PerkIconSize, PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, false);
return true;
} }
} simulated final function DrawPlayerInfoBar( KFPawn P, float BarPercentage, float BarLength, float BarHeight, float XPos, float YPos, Color BarColor, byte FadeAlpha, optional bool bDrawingHealth )
simulated final function DrawPlayerInfoBar( KFPawn P, float BarPercentage, float BarLength, float BarHeight, float XPos, float YPos, Color BarColor, optional bool bDrawingHealth )
{ {
//background for status bar //background for status bar
Canvas.SetDrawColorStruct(DrawToDistance(P, PlayerBarBGColor)); Canvas.DrawColor = PlayerBarBGColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(XPos, YPos); Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength, BarHeight, 0, 0, 32, 32); Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength, BarHeight, 0, 0, 32, 32);
@ -767,7 +795,8 @@ simulated final function DrawPlayerInfoBar( KFPawn P, float BarPercentage, float
BarHeight-=2; BarHeight-=2;
//Forground for status bar. //Forground for status bar.
Canvas.SetDrawColorStruct(DrawToDistance(P, BarColor)); Canvas.DrawColor = BarColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(XPos, YPos); Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength * BarPercentage, BarHeight, 0, 0, 32, 32); Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength * BarPercentage, BarHeight, 0, 0, 32, 32);
@ -777,11 +806,76 @@ simulated final function DrawPlayerInfoBar( KFPawn P, float BarPercentage, float
XPos+=(BarLength * BarPercentage); XPos+=(BarLength * BarPercentage);
BarPercentage = FMin(float(ExtHumanPawn(P).RepRegenHP) / float(P.HealthMax),1.f-BarPercentage); BarPercentage = FMin(float(ExtHumanPawn(P).RepRegenHP) / float(P.HealthMax),1.f-BarPercentage);
Canvas.DrawColor = DrawToDistance(P, MakeColor(255,128,128,255)); Canvas.DrawColor = MakeColor(255,128,128,FadeAlpha);
Canvas.SetPos(XPos, YPos); Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength * BarPercentage, BarHeight, 0, 0, 32, 32); Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength * BarPercentage, BarHeight, 0, 0, 32, 32);
} }
} }
simulated function DrawPerkIcons(KFPawn_Human KFPH, float PerkIconSize, float PerkIconPosX, float PerkIconPosY, float SupplyIconPosX, float SupplyIconPosY, bool bDropShadow)
{
local byte PrestigeLevel;
local ExtPlayerReplicationInfo KFPRI;
local color TempColor;
local float ResModifier;
KFPRI = ExtPlayerReplicationInfo(KFPH.PlayerReplicationInfo);
if (KFPRI == none)
{
return;
}
PrestigeLevel = KFPRI.GetActivePerkPrestigeLevel();
ResModifier = WorldInfo.static.GetResolutionBasedHUDScale() * FriendlyHudScale;
if (KFPRI.CurrentVoiceCommsRequest == VCT_NONE && KFPRI.ECurrentPerk != none && PrestigeLevel > 0)
{
Canvas.SetPos(PerkIconPosX, PerkIconPosY);
Canvas.DrawTile(KFPRI.ECurrentPerk.default.BasePerk.default.PrestigeIcons[PrestigeLevel - 1], PerkIconSize, PerkIconSize, 0, 0, 256, 256);
}
if (PrestigeLevel > 0)
{ //icon slot in image is not centered
Canvas.SetPos(PerkIconPosX + (PerkIconSize * (1 - PrestigeIconScale)) / 2, PerkIconPosY + PerkIconSize * 0.05f);
Canvas.DrawTile(KFPRI.GetCurrentIconToDisplay(), PerkIconSize * PrestigeIconScale, PerkIconSize * PrestigeIconScale, 0, 0, 256, 256);
}
else
{
Canvas.SetPos(PerkIconPosX, PerkIconPosY);
Canvas.DrawTile(KFPRI.GetCurrentIconToDisplay(), PerkIconSize, PerkIconSize, 0, 0, 256, 256);
}
if (KFPRI.PerkSupplyLevel > 0 && KFPRI.ECurrentPerk.default.BasePerk.static.GetInteractIcon() != none)
{
if (!bDropShadow)
{
if (KFPRI.PerkSupplyLevel == 2)
{
if (KFPRI.bPerkPrimarySupplyUsed && KFPRI.bPerkSecondarySupplyUsed)
{
TempColor = SupplierActiveColor;
}
else if (KFPRI.bPerkPrimarySupplyUsed || KFPRI.bPerkSecondarySupplyUsed)
{
TempColor = SupplierHalfUsableColor;
}
else
{
TempColor = SupplierUsableColor;
}
}
else if (KFPRI.PerkSupplyLevel == 1)
{
TempColor = KFPRI.bPerkPrimarySupplyUsed ? SupplierActiveColor : SupplierUsableColor;
}
Canvas.SetDrawColorStruct(TempColor);
}
Canvas.SetPos(SupplyIconPosX, SupplyIconPosY); //offset so that supplier icon shows up on the correct side of the player's health bar
Canvas.DrawTile(KFPRI.ECurrentPerk.default.BasePerk.static.GetInteractIcon(), (PlayerStatusIconSize * 0.75) * ResModifier, (PlayerStatusIconSize * 0.75) * ResModifier, 0, 0, 256, 256);
}
}
simulated function DrawMonsterHUD( KFPawn KFPH ) simulated function DrawMonsterHUD( KFPawn KFPH )
{ {
local float Percentage; local float Percentage;
@ -790,11 +884,13 @@ simulated function DrawMonsterHUD( KFPawn KFPH )
local Ext_T_MonsterPRI PRI; local Ext_T_MonsterPRI PRI;
local FontRenderInfo MyFontRenderInfo; local FontRenderInfo MyFontRenderInfo;
local float FontScale; local float FontScale;
local byte FadeAlpha;
PRI = Ext_T_MonsterPRI(KFPH.PlayerReplicationInfo); PRI = Ext_T_MonsterPRI(KFPH.PlayerReplicationInfo);
if( PRI==None ) if( PRI==None )
return; return;
FadeAlpha = DrawToDistance(KFPH);
MyFontRenderInfo = Canvas.CreateFontRenderInfo( true ); MyFontRenderInfo = Canvas.CreateFontRenderInfo( true );
BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale; BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale;
@ -808,12 +904,12 @@ simulated function DrawMonsterHUD( KFPawn KFPH )
//Draw health bar //Draw health bar
Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax),1.f); Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax),1.f);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor); DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor, FadeAlpha);
//Draw player name (Top) //Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale; FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont(); Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
Canvas.DrawColor = DrawToDistance(KFPH, (PRI.OwnerPRI==PlayerOwner.PlayerReplicationInfo ? MakeColor(32,250,32,255) : MakeColor(250,32,32,255))); Canvas.DrawColor = PRI.OwnerPRI==PlayerOwner.PlayerReplicationInfo ? MakeColor(32,250,32,FadeAlpha) : MakeColor(250,32,32,FadeAlpha);
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 3); Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 3);
Canvas.DrawText( PRI.PlayerName,,FontScale,FontScale, MyFontRenderInfo ); Canvas.DrawText( PRI.PlayerName,,FontScale,FontScale, MyFontRenderInfo );
@ -866,18 +962,16 @@ simulated function DrawPetInfo()
} }
} }
function Color DrawToDistance(KFPawn Pawn, Color DrawColor) function byte DrawToDistance(Actor A, optional float StartAlpha=255.f, optional float MinAlpha=90.f)
{ {
local float Dist, fZoom; local float Dist, fZoom;
Dist = VSize(Pawn.Location - PLCameraLoc) * 0.5; Dist = VSize(A.Location - PLCameraLoc);
if ( Dist <= HealthBarFullVisDist || PlayerOwner.PlayerReplicationInfo.bOnlySpectator ) if ( Dist <= HealthBarFullVisDist || PlayerOwner.PlayerReplicationInfo.bOnlySpectator )
fZoom = 1.0; fZoom = 1.0;
else fZoom = FMax(1.0 - (Dist - HealthBarFullVisDist) / (HealthBarCutoffDist - HealthBarFullVisDist), 0.0); else fZoom = FMax(1.0 - (Dist - HealthBarFullVisDist) / (HealthBarCutoffDist - HealthBarFullVisDist), 0.0);
DrawColor.A = Clamp(255 * fZoom, 90, 255); return Clamp(StartAlpha * fZoom, MinAlpha, StartAlpha);
return DrawColor;
} }
final function AddNumberMsg( int Amount, vector Pos, byte Type ) final function AddNumberMsg( int Amount, vector Pos, byte Type )
@ -1059,13 +1153,13 @@ simulated final function DrawItemsList()
Canvas.TextSize(NewItems[i].Item,XS,YS,FontScale,FontScale); Canvas.TextSize(NewItems[i].Item,XS,YS,FontScale,FontScale);
if( NewItems[i].Icon!=None ) /*if( NewItems[i].Icon!=None )
{ {
Canvas.SetPos(XPos-YSize,YPos); Canvas.SetPos(XPos-YSize,YPos);
Canvas.DrawRect(YSize,YSize,NewItems[i].Icon); Canvas.DrawRect(YSize,YSize,NewItems[i].Icon);
XS = XPos-(YSize*1.1)-XS; XS = XPos-(YSize*1.1)-XS;
} }
else XS = XPos-XS; else */XS = XPos-XS;
Canvas.SetPos(XS,YPos); Canvas.SetPos(XS,YPos);
Canvas.DrawText("New Item:",,FontScale,FontScale); Canvas.DrawText("New Item:",,FontScale,FontScale);

View File

@ -0,0 +1,5 @@
Class SRPerkManager extends ExtPerkManager;
defaultproperties
{
}

View File

@ -49,6 +49,7 @@ var int LastWaveNum,NumWaveSwitches;
var ExtSpawnPointHelper SpawnPointer; var ExtSpawnPointHelper SpawnPointer;
var bool bRespawnCheck,bSpecialSpawn,bGameHasEnded,bIsPostGame; var bool bRespawnCheck,bSpecialSpawn,bGameHasEnded,bIsPostGame;
var config bool bKillMessages,bDamageMessages,bEnableMapVote,bNoAdminCommands,bNoWebAdmin,bNoBoomstickJumping,bDumpXMLStats,bRagdollFromFall,bRagdollFromMomentum,bRagdollFromBackhit,bAddCountryTags; var config bool bKillMessages,bDamageMessages,bEnableMapVote,bNoAdminCommands,bNoWebAdmin,bNoBoomstickJumping,bDumpXMLStats,bRagdollFromFall,bRagdollFromMomentum,bRagdollFromBackhit,bAddCountryTags;
var config bool bServerPerksMode;
function PostBeginPlay() function PostBeginPlay()
{ {
@ -426,7 +427,7 @@ final function GT_PlayerKilled( Controller Killer, Controller Killed, class<Dama
if( KFG!=None && KFPC != none && MonsterPawn!=none ) if( KFG!=None && KFPC != none && MonsterPawn!=none )
{ {
//Chris: We have to do it earlier here because we need a damage type //Chris: We have to do it earlier here because we need a damage type
KFPC.AddZedKill( MonsterPawn.class, KFG.GameDifficulty, damageType ); KFPC.AddZedKill( MonsterPawn.class, KFG.GameDifficulty, damageType, false );
if( KFPC.ActivePerkManager!=none && KFPC.ActivePerkManager.CanEarnSmallRadiusKillXP(damageType) ) if( KFPC.ActivePerkManager!=none && KFPC.ActivePerkManager.CanEarnSmallRadiusKillXP(damageType) )
KFG.CheckForBerserkerSmallRadiusKill( MonsterPawn, KFPC ); KFG.CheckForBerserkerSmallRadiusKill( MonsterPawn, KFPC );