/** * * Copyright 2012-2015 Gears for Breakfast ApS. All Rights Reserved. */ class mcu8_NPC_Player extends Hat_NPC dependson(Hat_ExpressionComponent) abstract; var Array MyInventory; var transient PlayerController PlayerOwner; var transient bool HasUpdatedVisualsOnce; var Hat_TextRenderComponent TextRenderComponent; var MeshComponent PreviewMeshes[2]; var(CustomNPC_Visuals) bool GiveWeapon; var(CustomNPC_Visuals) class WeaponClass; var(CustomNPC_Visuals) bool WeaponInitiallyVisible; var(CustomNPC_Visuals) class HatClass; var(CustomNPC_Visuals) class HatQualityInfo; var(CustomNPC_Visuals) class MySkinClass; var(CustomNPC_Visuals) string DisplayName; var(CustomNPC_Visuals) Color DisplayColor; var(CustomNPC_Animations) Name InitialAnimation; var(CustomNPC_Animations) bool Loop; var(CustomNPC_Animations) bool Restart; var(CustomNPC_Animations) float PlayRate; var(CustomNPC_Animations) float AnimationDuration; var(CustomNPC_Expressions) EExpressionType InitialExpression; var(CustomNPC_Expressions) bool MakeDefault; var(CustomNPC_Expressions) float Duration; var(Cosmetics) bool DisableUpperBody; var(Cosmetics) bool DisableLegs; var(Cosmetics) bool DisableHats; var(Cosmetics) bool DisableMasks; // If we don't want to cover the player's face in this cinematic, turn this on var bool IsLowQuality; // Sets IsLowQuality on its cosmeticitems var transient protected class CurrentSkinClass; function OnEnabled() { Super.OnEnabled(); UpdateVisuals(); } simulated event PostBeginPlay() { Super.PostBeginPlay(); if (!HasUpdatedVisualsOnce) UpdateVisuals(); } simulated event Destroyed() { DiscardInventory(); Super.Destroyed(); } function PlayAnimationMy(SkeletalMeshComponent c, bool IsPlay) { local float dur; local AnimNodeSlot slot; if (c.AnimTreeTemplate != None) { foreach c.AllAnimNodes(class'AnimNodeSlot', slot) { if (InitialAnimation == '' || !IsPlay) slot.StopCustomAnim(0.1); else { slot.PlayCustomAnim(InitialAnimation, PlayRate, 0.1, 0.1, Loop); } break; } return; } dur = 0.0; if (PlayRate > 0 && AnimationDuration > 0) dur = AnimationDuration / PlayRate; c.PlayAnim(InitialAnimation, dur, Loop, Restart); } function SetExpression(Actor Act, EExpressionType Exp, optional float d) { local Hat_ExpressionComponent Cmp; Cmp = GetActorExpression(Act); if (Cmp == None) { /* Cmp = new(Act) class'Hat_ExpressionComponent_HatKid'; Act.AttachComponent(Cmp); Cmp.Init(); if (Hat_SkeletalMeshActor(Act) != None) Hat_SkeletalMeshActor(Act).ExpressionComponent = Cmp; */ return; } if (MakeDefault) { Cmp.SetDefaultExpression(Exp); } else { Cmp.SetExpression(Exp, d); } if (Exp == EExpressionType_Ignore) { Expression.Reset(); Expression.Init(); } } static function Hat_ExpressionComponent GetActorExpression(Actor Act) { local Hat_ExpressionComponent Cmp; foreach Act.ComponentList(class'Hat_ExpressionComponent', Cmp) return Cmp; return None; } function UpdateVisuals() { local int i; for (i = 0; i < 2; i++) { if (PreviewMeshes[i] == None) continue; DetachComponent(PreviewMeshes[i]); PreviewMeshes[i] = None; } AttachComponent(Expression); Expression.Reset(); Expression.Init(); AddDefaultInventory(); HasUpdatedVisualsOnce = true; PlayAnimationMy(SkeletalMeshComponent, true); If (Expression != None) { SetExpression(Self, InitialExpression, Duration); } TextRenderComponent.Text = DisplayName; TextRenderComponent.TextColor = DisplayColor; TextRenderComponent.SetHidden(DisplayName == ""); ReattachComponent(TextRenderComponent); } function AddDefaultInventory() { DiscardInventory(); CreateInventoryForPlayerTypeNPC(); CreateInventory(HatClass, HatQualityInfo); GiveUmbrella(); ShowWeapon(WeaponInitiallyVisible); if (MySkinClass != None) { InitMaterialInstances(); CurrentSkinClass = MySkinClass; CurrentSkinClass.static.Apply(self); } } function CreateInventoryForPlayerTypeNPC(); function Array GetMyMaterialMeshComponents(optional bool attachments) { local Array OutArray; local Inventory Inv; local MeshComponent Mesh; OutArray = Super.GetMyMaterialMeshComponents(attachments); foreach MyInventory(Inv) { Mesh = MeshComponent(Inv.DroppedPickupMesh); if (Mesh != None) { OutArray.AddItem(Mesh); } } return OutArray; } simulated expensive function InitMaterialInstances() { local Inventory Inv; local MeshComponent Mesh; Super.InitMaterialInstances(); foreach MyInventory(Inv) { Mesh = MeshComponent(Inv.DroppedPickupMesh); if (Mesh != None) { InitMaterialInstancesMesh(Mesh); if (Inv.IsA('Hat_CosmeticItem')) Hat_CosmeticItem(Inv).OnInitInventoryMaterialInstancesQualityInfo(Mesh, Hat_CosmeticItem(Inv).MyItemQualityInfo); } } // We have to re-initialize expression any time after if (Expression != None) { Expression.Reset(); Expression.Init(); } } function GiveLoadoutItem(Hat_BackpackItem InvClass) { if (class(InvClass.BackpackClass) == None) return; CreateInventory(class(InvClass.BackpackClass), InvClass.IsA('Hat_LoadoutBackpackItem') ? Hat_LoadoutBackpackItem(InvClass).ItemQualityInfo : None); } function Inventory CreateInventory(class c, optional class ItemQualityInfo) { local Inventory Inv; local Hat_CosmeticItem cos; local Name SpawnTag; // We have a custom tag set, so likely we're set to a specific cubemap. Our items should be too SpawnTag = ''; if (InStr(Locs(string(Tag)), "hat_npc_player") == INDEX_NONE) { SpawnTag = Tag; } Inv = Spawn(c, None, SpawnTag,,,,true); if (Inv == None) return None; MyInventory.AddItem(Inv); cos = Hat_CosmeticItem(Inv); if (cos != None) { // MEKU TO-DO: Work out why Instigator is set? cos.Instigator = None; cos.ActorInstigator = None; if (ItemQualityInfo != None) cos.UpdateItemQuality(ItemQualityInfo); cos.ActorInstigator = self; cos.IsLowQuality = IsLowQuality; if (Hat_Ability(Inv) != None) { Hat_Ability(Inv).UpdateArrayIndex(); } if (!cos.AttachToOwner(self, cos.MyItemQualityInfo)) { `if(`notdefined(FINAL_RELEASE)) `broadcast("AttachToOwner failed: " $ c); `endif } cos.SetOcclusionHidden(true); if (cos.DroppedPickupMesh != None) cos.DroppedPickupMesh.SetDepthPriorityGroup(SkeletalMeshComponent.DepthPriorityGroup); if (!IsLowQuality && cos.DroppedPickupMesh != None && SkeletalMeshComponent(cos.DroppedPickupMesh) != None) SkeletalMeshComponent(cos.DroppedPickupMesh).SetHasPhysicsAssetInstance(SkeletalMeshComponent.bHasPhysicsAssetInstance); if (!IsLowQuality && cos.OccludedMesh != None && SkeletalMeshComponent(cos.OccludedMesh) != None) SkeletalMeshComponent(cos.OccludedMesh).SetHasPhysicsAssetInstance(SkeletalMeshComponent.bHasPhysicsAssetInstance); } else if (Inv.IsA('Hat_Weapon')) { if (Inv.DroppedPickupMesh != None) Hat_Weapon(Inv).AttachMeshToOwner(self, Inv.DroppedPickupMesh); } return Inv; } function DiscardInventory() { local int i; for (i = MyInventory.Length-1; i >= 0; i--) { MyInventory[i].ItemRemovedFromInvManager(); MyInventory[i].Destroy(); } MyInventory.Length = 0; SkeletalMeshComponent.SetSectionGroup(''); // We have to un-apply the skin by applying the default skin (which resets parameters) if (CurrentSkinClass != None) { //`broadcast("Removed: " $ CurrentSkinClass); CurrentSkinClass.static.Removed(self); CurrentSkinClass = None; class'Hat_Collectible_Skin'.static.Apply(self); if (Expression != None) { Expression.Reset(); Expression.Init(); } } } simulated function ShowWeapon(bool b) { local int i; for (i = 0; i < MyInventory.Length; i++) { if (!MyInventory[i].IsA('Hat_Weapon')) continue; MyInventory[i].SetHidden(!b); if (MyInventory[i].IsA('Hat_Weapon_Umbrella')) Hat_Weapon_Umbrella(MyInventory[i]).TakeOut(); } } function bool GiveUmbrella() { local Hat_BackpackItem bi; if (!GiveWeapon) return false; bi = new class'Hat_BackpackItem'; bi.BackpackClass = WeaponClass; GiveLoadoutItem(bi); return true; } function bool IsTooFarAway() { return false; } defaultproperties { Begin Object Class=Hat_TextRenderComponent Name=TextRenderComponent0 Translation=(Z=115) Size = 0.8f TextLimit = 50 HiddenGame=false TextColor=(R=127,G=187,B=213) CastShadow = false //Rotation=(Yaw=-16384) End Object TextRenderComponent = TextRenderComponent0; Components.Add(TextRenderComponent0) TickOptimize = TickOptimize_None; bBlockActors = false; bCollideWorld = true; bCollideActors = true; BlockRigidBody = false; bPathColliding = false; bCanBeDamaged = true; GiveWeapon = false; WeaponInitiallyVisible = false; WeaponClass = class'Hat_Weapon_Umbrella'; HatClass = class'Hat_Ability_Help'; HatQualityInfo = None; InitialAnimation = "Idle" Loop = true; Restart = false; PlayRate = 1.0; AnimationDuration = 0.0; DisplayColor=(R=127,G=187,B=213) Duration = 0; }