Prepare fixtures
This commit is contained in:
parent
797e5ea192
commit
9c94356263
6021 changed files with 722805 additions and 22 deletions
39
kf_sources/KFStoryGame/Classes/ACTION_CashReward.uc
Normal file
39
kf_sources/KFStoryGame/Classes/ACTION_CashReward.uc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//-----------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
class ACTION_CashReward extends ScriptedAction
|
||||
editinlinenew;
|
||||
|
||||
var () int BaseCashAmount;
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
local Controller Controller;
|
||||
|
||||
if(Abs(BaseCashAmount) > 0)
|
||||
{
|
||||
for ( Controller = C.Level.ControllerList; Controller != none; Controller = Controller.NextController )
|
||||
{
|
||||
if(Controller.PlayerReplicationInfo != none &&
|
||||
Controller.Pawn != none &&
|
||||
Controller.Pawn.Health > 0)
|
||||
{
|
||||
Controller.PlayerReplicationInfo.Score += BaseCashAmount ;
|
||||
|
||||
if(PlayerController(Controller) != none)
|
||||
{
|
||||
PlayerController(Controller).ClientPlaySound(class 'CashPickup'.default.PickupSound);
|
||||
PlayerController(Controller).ReceiveLocalizedMessage(class 'Msg_CashReward',BaseCashAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
24
kf_sources/KFStoryGame/Classes/ACTION_ChangeConditionLoc.uc
Normal file
24
kf_sources/KFStoryGame/Classes/ACTION_ChangeConditionLoc.uc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
class ACTION_ChangeConditionLoc extends ScriptedAction;
|
||||
|
||||
var () KF_ObjectiveCondition AssociatedCondition;
|
||||
var () actor NewLocation;
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
if(AssociatedCondition != none)
|
||||
{
|
||||
AssociatedCondition.HUD_World.World_Location = NewLocation;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function string GetActionString()
|
||||
{
|
||||
return ActionString;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ActionString="Update Condition Loc"
|
||||
}
|
||||
81
kf_sources/KFStoryGame/Classes/ACTION_ChangeViewtarget.uc
Normal file
81
kf_sources/KFStoryGame/Classes/ACTION_ChangeViewtarget.uc
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
ACTION_ChangeViewTarget
|
||||
--------------------------------------------------------------
|
||||
|
||||
Scripted Action used to switch players viewtarget to a specific actor.
|
||||
Used in story mode for the Patriarch 'Grand Entrance' sequence.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
class ACTION_ChangeViewTarget extends ScriptedAction;
|
||||
|
||||
var() name ViewActorTag;
|
||||
var bool bViewingActor;
|
||||
|
||||
|
||||
/* Initialises this action ** NOTE : returning TRUE out of this function will pause
|
||||
all subsequent actions. you must return false if you want the scripted actions to proceed*/
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
local Controller CC;
|
||||
local PlayerController PC;
|
||||
local Actor TestActor, ViewActor;
|
||||
|
||||
if(ViewActorTag != '')
|
||||
{
|
||||
foreach AllObjects(class 'Actor', TestActor)
|
||||
{
|
||||
if(TestActor.Tag == ViewActorTag)
|
||||
{
|
||||
ViewActor = TestActor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bViewingActor = ViewActor != none ;
|
||||
for ( CC = C.Level.ControllerList; CC != None; CC = CC.NextController )
|
||||
{
|
||||
PC = PlayerController(CC);
|
||||
if( PC !=None )
|
||||
{
|
||||
if(ViewActorTag != '')
|
||||
{
|
||||
log("! Change View Target to : "@ViewActor,'Story_Debug');
|
||||
ViewActor.bAlwaysRelevant = True;
|
||||
PC.SetViewTarget(ViewActor);
|
||||
PC.ClientSetViewTarget(ViewActor);
|
||||
PC.bBehindView = True;
|
||||
PC.ClientSetBehindView(True);
|
||||
|
||||
if(KFMonster(ViewActor) != none)
|
||||
{
|
||||
KFMonster(ViewActor).MakeGrandEntry();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log("! Change View Target to : "@PC.Pawn,'Story_Debug');
|
||||
if( PC.Pawn!=None )
|
||||
{
|
||||
PC.SetViewTarget(PC.Pawn);
|
||||
PC.ClientSetViewTarget(PC.Pawn);
|
||||
}
|
||||
else
|
||||
{
|
||||
PC.SetViewTarget(PC);
|
||||
PC.ClientSetViewTarget(PC);
|
||||
}
|
||||
|
||||
PC.bBehindView = False;
|
||||
PC.ClientSetBehindView(False);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
118
kf_sources/KFStoryGame/Classes/ACTION_DropInventory.uc
Normal file
118
kf_sources/KFStoryGame/Classes/ACTION_DropInventory.uc
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
class ACTION_DropInventory extends ScriptedAction;
|
||||
|
||||
var() class<Inventory> InventoryType;
|
||||
var() name InvTag;
|
||||
var() bool bSpawnPickup;
|
||||
var() bool bAlwaysDropFromInstigator; // Should we always drop the pickup from the guy who instigates this action, or do we not care?
|
||||
|
||||
/* C.GetInstigator() is unreliable in this case, because a different player than the one who's inventory Item we
|
||||
need to remove could be instigating the trigger*/
|
||||
|
||||
function Pawn GetInvHolder( ScriptedController OwningController, out Inventory ItemToRemove)
|
||||
{
|
||||
local Controller C;
|
||||
|
||||
if(bAlwaysDropFromInstigator && OwningController.GetInstigator() != none)
|
||||
{
|
||||
ItemToRemove = OwningController.GetInstigator().FindInventoryType(InventoryType);
|
||||
|
||||
if(ItemToRemove != none &&
|
||||
(InvTag == '' || ItemToRemove.Tag == InvTag))
|
||||
{
|
||||
return OwningController.GetInstigator();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( C=OwningController.Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if(C.Pawn != none && C.Pawn.bCanPickupInventory)
|
||||
{
|
||||
ItemToRemove = C.Pawn.FindInventoryType(InventoryType) ;
|
||||
|
||||
if(ItemToRemove != none &&
|
||||
(InvTag == '' || ItemToRemove.Tag == InvTag))
|
||||
{
|
||||
return C.Pawn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return none;
|
||||
}
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
local Inventory DelInv;
|
||||
local Pawn P;
|
||||
local PlayerController PC, OPC;
|
||||
local class<Pickup> PickupClass;
|
||||
local bool bSwitchWeapons;
|
||||
local Controller CLC;
|
||||
|
||||
P = GetInvHolder(C,DelInv);
|
||||
if( P == none || DelInv == none)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bSwitchWeapons = (DelInv == P.Weapon);
|
||||
|
||||
if( bSpawnPickup )
|
||||
{
|
||||
DelInv.Velocity = Vector( P.Rotation ) * 250.f ;
|
||||
DelInv.DropFrom( P.Location );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( KFHumanPawn_Story( P ) != none)
|
||||
{
|
||||
KFHumanPawn_Story( P ).SetHasStoryItem( false );
|
||||
}
|
||||
|
||||
if(KF_StoryInventoryItem(DelInv) != none)
|
||||
{
|
||||
KF_StoryInventoryItem(DelInv).UpdateHeldMaterial(P,none);
|
||||
}
|
||||
|
||||
DelInv.DetachFromPawn(P);
|
||||
P.DeleteInventory( DelInv );
|
||||
DelInv.Destroy();
|
||||
}
|
||||
|
||||
// JDR: TODO - re-add DeleteAmmo to Weapon and KFWeapon
|
||||
//if( Weapon(DelInv) != none )
|
||||
//{
|
||||
// Weapon( DelInv ).DeleteAmmo();
|
||||
//}
|
||||
|
||||
OPC = PlayerController(P.Controller);
|
||||
if( OPC != none && bSwitchWeapons )
|
||||
{
|
||||
OPC.ClientSwitchToBestWeapon();
|
||||
}
|
||||
|
||||
PickupClass = InventoryType.default.PickupClass;
|
||||
if( PickupClass != none )
|
||||
{
|
||||
for( CLC = P.Level.ControllerList; CLC != None; CLC = CLC.NextController )
|
||||
{
|
||||
PC = PlayerController(CLC);
|
||||
if(PC != none)
|
||||
{
|
||||
// JDR: there is no unified way to retrieve a "dropped" message currently,
|
||||
// so this only displays the correct message for the gold bar for now,
|
||||
// which is all we're using this for, for now...
|
||||
PC.ReceiveLocalizedMessage(PickupClass.default.MessageClass,3,OPC.PlayerReplicationInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ActionString="Delete Inventory"
|
||||
}
|
||||
62
kf_sources/KFStoryGame/Classes/ACTION_GiveWaveEndCash.uc
Normal file
62
kf_sources/KFStoryGame/Classes/ACTION_GiveWaveEndCash.uc
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
class ACTION_GiveWaveEndCash extends ScriptedAction
|
||||
editinlinenew;
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
local Controller PC;
|
||||
local int moneyPerPlayer,div;
|
||||
local TeamInfo T;
|
||||
|
||||
for ( PC = C.Level.ControllerList; PC != none; PC = PC.NextController )
|
||||
{
|
||||
if ( PC.Pawn != none && PC.PlayerReplicationInfo != none && PC.PlayerReplicationInfo.Team != none )
|
||||
{
|
||||
T = PC.PlayerReplicationInfo.Team;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( T == none || T.Score <= 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
moneyPerPlayer = int(T.Score / float(div));
|
||||
|
||||
for ( PC = C.Level.ControllerList; PC != none; PC = PC.NextController )
|
||||
{
|
||||
if ( PC.Pawn != none && PC.PlayerReplicationInfo != none && PC.PlayerReplicationInfo.Team != none )
|
||||
{
|
||||
if ( div == 1 )
|
||||
{
|
||||
PC.PlayerReplicationInfo.Score += T.Score;
|
||||
T.Score = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PC.PlayerReplicationInfo.Score += moneyPerPlayer;
|
||||
T.Score-=moneyPerPlayer;
|
||||
div--;
|
||||
}
|
||||
|
||||
if(PlayerController(PC) != none)
|
||||
{
|
||||
PlayerController(PC).ClientPlaySound(class 'CashPickup'.default.PickupSound);
|
||||
PlayerController(PC).ReceiveLocalizedMessage(class 'Msg_CashReward',MoneyPerPlayer);
|
||||
}
|
||||
|
||||
PC.PlayerReplicationInfo.NetUpdateTime = C.Level.TimeSeconds - 1;
|
||||
|
||||
if( T.Score <= 0 )
|
||||
{
|
||||
T.Score = 0;
|
||||
Break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
107
kf_sources/KFStoryGame/Classes/ACTION_OpenRandomTrader.uc
Normal file
107
kf_sources/KFStoryGame/Classes/ACTION_OpenRandomTrader.uc
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
class ACTION_OpenRandomTrader extends ScriptedAction;
|
||||
|
||||
var () bool bCloseOtherShops;
|
||||
var () bool bOpenDoor;
|
||||
var () bool bUseExistingShop;
|
||||
var ShopVolume CurrentShop;
|
||||
|
||||
var array<ShopVolume> Shops;
|
||||
|
||||
function CacheShops()
|
||||
{
|
||||
local ShopVolume Shop;
|
||||
|
||||
Shops.length = 0 ;
|
||||
foreach AllObjects(class 'ShopVolume', Shop)
|
||||
{
|
||||
Shops[Shops.length] = Shop ;
|
||||
}
|
||||
}
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
CacheShops();
|
||||
CurrentShop = GetCurrentShop(C);
|
||||
|
||||
if(!bUseExistingShop || CurrentShop == none)
|
||||
{
|
||||
FindNewShop(C);
|
||||
}
|
||||
|
||||
HandleShops();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function FindNewShop(ScriptedController C)
|
||||
{
|
||||
local ShopVolume NewShop;
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
NewShop = Shops[Rand(Shops.length)] ;
|
||||
KFGRI = KFGameReplicationInfo(C.Level.game.GameReplicationInfo) ;
|
||||
if(KFGRI != none)
|
||||
{
|
||||
KFGRI.CurrentShop = NewShop;
|
||||
}
|
||||
CurrentShop = KFGRi.CurrentShop ;
|
||||
HandleShops();
|
||||
}
|
||||
|
||||
function HandleShops()
|
||||
{
|
||||
if(CurrentShop != none)
|
||||
{
|
||||
if(bOpenDoor && !CurrentShop.bCurrentlyOpen)
|
||||
{
|
||||
OpenSelectedShop();
|
||||
}
|
||||
|
||||
CloseOtherShops();
|
||||
}
|
||||
}
|
||||
|
||||
function CloseOtherShops()
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(bCloseOtherShops)
|
||||
{
|
||||
for(i = 0 ; i < Shops.length ; i ++)
|
||||
{
|
||||
if(Shops[i].bCurrentlyOpen)
|
||||
{
|
||||
Shops[i].BootPlayers();
|
||||
Shops[i].CloseShop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ShopVolume GetCurrentShop(ScriptedController C)
|
||||
{
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
KFGRI = KFGameReplicationInfo(C.Level.game.GameReplicationInfo) ;
|
||||
if(KFGRI != none)
|
||||
{
|
||||
return KFGRi.CurrentShop ;
|
||||
}
|
||||
}
|
||||
|
||||
function OpenSelectedShop()
|
||||
{
|
||||
CurrentShop.InitTeleports();
|
||||
CurrentShop.OpenShop();
|
||||
}
|
||||
|
||||
function string GetActionString()
|
||||
{
|
||||
return ActionString;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bCloseOtherShops = true
|
||||
ActionString="Open Random Trader Shop"
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
ACTION_ResetPlayerPerkSelection
|
||||
--------------------------------------------------------------
|
||||
|
||||
Force allows players to be able to change their perks.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ACTION_ResetPlayerPerkSelection extends ScriptedAction;
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
local Controller Controller;
|
||||
local KFPC KFController;
|
||||
|
||||
for ( Controller = C.Level.ControllerList; Controller != none; Controller = Controller.NextController )
|
||||
{
|
||||
KFController = KFPC(Controller);
|
||||
if(KFController != none)
|
||||
{
|
||||
KFController.bChangedVeterancyThisWave = false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
36
kf_sources/KFStoryGame/Classes/ACTION_SetCollision.uc
Normal file
36
kf_sources/KFStoryGame/Classes/ACTION_SetCollision.uc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
class ACTION_SetCollision extends ScriptedAction;
|
||||
|
||||
var(Action) bool bShouldCollideActors,bShouldBlockActors;
|
||||
var(Action) name CollisionActorTag;
|
||||
|
||||
var Array<Actor> Target;
|
||||
|
||||
event PostBeginPlay( ScriptedSequence SS )
|
||||
{
|
||||
local Actor A;
|
||||
|
||||
if ( CollisionActorTag != '' )
|
||||
{
|
||||
ForEach SS.AllActors(class'Actor', A, CollisionActorTag)
|
||||
Target[Target.Length] = A;
|
||||
}
|
||||
}
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if ( Target.Length > 0 )
|
||||
{
|
||||
For (i=0; i<Target.Length; i++)
|
||||
{
|
||||
Target[i].SetCollision(bShouldCollideActors,bShouldBlockActors);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
C.GetInstigator().SetCollision(bShouldCollideActors,bShouldBlockActors);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
33
kf_sources/KFStoryGame/Classes/ACTION_ToggleStoryNPCs.uc
Normal file
33
kf_sources/KFStoryGame/Classes/ACTION_ToggleStoryNPCs.uc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
|
||||
Turns all KF_StoryNPCs in the map off or on.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ACTION_ToggleStoryNPCs extends ScriptedAction;
|
||||
|
||||
enum ENPCState
|
||||
{
|
||||
Off,
|
||||
On
|
||||
};
|
||||
|
||||
var () ENPCState DesiredState;
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
local KF_StoryNPC A;
|
||||
|
||||
foreach C.AllActors(class 'KF_StoryNPC', A)
|
||||
{
|
||||
A.SetActive(bool(DesiredState));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
65
kf_sources/KFStoryGame/Classes/ACTION_TriggerRandomEvents.uc
Normal file
65
kf_sources/KFStoryGame/Classes/ACTION_TriggerRandomEvents.uc
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
ACTION_TriggerRandomEvents
|
||||
--------------------------------------------------------------
|
||||
|
||||
Functions like 'ACTION_TriggerEvent' except that it supports
|
||||
multiple different events being fired off at once. It will pick
|
||||
up to 'NumToTrigger' events from the 'PossibleEvents' array
|
||||
in order to do this.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ACTION_TriggerRandomEvents extends ScriptedAction;
|
||||
|
||||
var(Action) array<name> PossibleEvents;
|
||||
|
||||
var(Action) int NumToTrigger;
|
||||
|
||||
function bool InitActionFor(ScriptedController C)
|
||||
{
|
||||
local array<name> EventList,PendingEvents;
|
||||
local int RandIdx;
|
||||
local int i;
|
||||
|
||||
EventList = PossibleEvents;
|
||||
|
||||
/* Always check that we're not trying to trigger more events than are in the array */
|
||||
NumToTrigger = Min(NumToTrigger,EventList.length);
|
||||
|
||||
for(i = 0 ; i < NumToTrigger; i ++)
|
||||
{
|
||||
RandIdx = Rand(EventList.length);
|
||||
|
||||
PendingEvents.length = PendingEvents.length + 1;
|
||||
PendingEvents[PendingEvents.length - 1] = EventList[RandIdx];
|
||||
|
||||
/* remove it from the list so it can't be used twice */
|
||||
EventList.Remove(RandIdx,1);
|
||||
}
|
||||
|
||||
for(i = 0 ; i < PendingEvents.length ; i ++)
|
||||
{
|
||||
C.TriggerEvent(PendingEvents[i],C.SequenceScript,C.GetInstigator());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function GetActionEvents(out array<name> TriggeredEvents, out array<name> ReceivedEvents)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for( i = 0 ; i < PossibleEvents.length ; i ++)
|
||||
{
|
||||
if(PossibleEvents[i] != '')
|
||||
{
|
||||
TriggeredEvents[TriggeredEvents.length] = PossibleEvents[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
64
kf_sources/KFStoryGame/Classes/AnimatedRachel.uc
Normal file
64
kf_sources/KFStoryGame/Classes/AnimatedRachel.uc
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
class AnimatedRachel extends Decoration; // Decoration
|
||||
|
||||
#exec OBJ LOAD FILE=KF_RachelC_anim.ukx
|
||||
|
||||
var bool bTriggered;
|
||||
var bool bTriggeredAnimation;
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
If ( Level.NetMode != NM_DedicatedServer)
|
||||
{
|
||||
LoopAnim('Idle_Fidget');
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
if ( Level.NetMode != NM_DedicatedServer )
|
||||
{
|
||||
if (!bTriggeredAnimation)
|
||||
{
|
||||
bTriggeredAnimation = TRUE;
|
||||
LoopAnim('Idle_Gesticulate');
|
||||
}
|
||||
ELSE
|
||||
{
|
||||
bTriggeredAnimation = FALSE;
|
||||
LoopAnim('Idle_Fidget');
|
||||
}
|
||||
}
|
||||
|
||||
bClientTrigger = !bClientTrigger;
|
||||
|
||||
}
|
||||
|
||||
simulated event ClientTrigger()
|
||||
{
|
||||
if ( Level.NetMode != NM_DedicatedServer )
|
||||
{
|
||||
if (!bTriggeredAnimation)
|
||||
{
|
||||
bTriggeredAnimation = TRUE;
|
||||
LoopAnim('Idle_Gesticulate');
|
||||
}
|
||||
ELSE
|
||||
{
|
||||
bTriggeredAnimation = FALSE;
|
||||
LoopAnim('Idle_Fidget');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bStatic=False
|
||||
bStasis=False
|
||||
Mesh=SkeletalMesh'KF_RachelC_anim.RachelC_mesh''
|
||||
DrawScale=1
|
||||
RemoteRole=ROLE_SimulatedProxy
|
||||
bNoDelete=True
|
||||
NetUpdateFrequency=0.5
|
||||
bSkipActorPropertyReplication=True
|
||||
bAlwaysRelevant=True
|
||||
}
|
||||
21
kf_sources/KFStoryGame/Classes/BlockingVolume_Toggleable.uc
Normal file
21
kf_sources/KFStoryGame/Classes/BlockingVolume_Toggleable.uc
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// A special type of volume which functions like a blocking volume, but blocks ONLY humans from entering
|
||||
|
||||
class BlockingVolume_Toggleable extends BlockingVolume;
|
||||
|
||||
function Reset()
|
||||
{
|
||||
SetCollision(default.bCollideActors);
|
||||
}
|
||||
|
||||
simulated function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
SetCollision(!bCollideActors);
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bClassBlocker=True
|
||||
BlockedClasses(0)=Class'KFMod.KFHumanPawn'
|
||||
bStatic = false
|
||||
}
|
||||
21
kf_sources/KFStoryGame/Classes/BreakerGibGroup.uc
Normal file
21
kf_sources/KFStoryGame/Classes/BreakerGibGroup.uc
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
class BreakerGibGroup extends xPawnGibGroup;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Gibs(0)=none
|
||||
Gibs(1)=none
|
||||
Gibs(2)=none
|
||||
Gibs(3)=none
|
||||
Gibs(4)=none
|
||||
Gibs(5)=none
|
||||
Gibs(6)=none
|
||||
Gibs(7)=none
|
||||
BloodHitClass=Class'Emitter_BreakerExplosion'
|
||||
LowGoreBloodHitClass=Class'Emitter_BreakerExplosion'
|
||||
BloodGibClass=Class'Emitter_BreakerExplosion'
|
||||
LowGoreBloodGibClass=Class'Emitter_BreakerExplosion'
|
||||
LowGoreBloodEmitClass=Class'Emitter_BreakerExplosion'
|
||||
BloodEmitClass=Class'Emitter_BreakerExplosion'
|
||||
NoBloodEmitClass=Class'Emitter_BreakerExplosion'
|
||||
NoBloodHitClass=Class'Emitter_BreakerExplosion'
|
||||
}
|
||||
15
kf_sources/KFStoryGame/Classes/BreakerSoundGroup.uc
Normal file
15
kf_sources/KFStoryGame/Classes/BreakerSoundGroup.uc
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
class BreakerSoundGroup extends xPawnSoundGroup;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DeathSounds(0)=Sound'PatchSounds.MetalCrash'
|
||||
DeathSounds(1)=Sound'PatchSounds.MetalCrash'
|
||||
DeathSounds(2)=Sound'PatchSounds.MetalCrash'
|
||||
DeathSounds(3)=Sound'PatchSounds.MetalCrash'
|
||||
DeathSounds(4)=Sound'PatchSounds.MetalCrash'
|
||||
PainSounds(0)=Sound'KF_EnemyGlobalSnd.Zomb_HitDoor_Metal'
|
||||
PainSounds(1)=Sound'KF_EnemyGlobalSnd.Zomb_HitDoor_Metal'
|
||||
PainSounds(2)=Sound'KF_EnemyGlobalSnd.Zomb_HitDoor_Metal'
|
||||
PainSounds(3)=Sound'KF_EnemyGlobalSnd.Zomb_HitDoor_Metal'
|
||||
PainSounds(4)=Sound'KF_EnemyGlobalSnd.Zomb_HitDoor_Metal'
|
||||
}
|
||||
36
kf_sources/KFStoryGame/Classes/CashPickup_Story.uc
Normal file
36
kf_sources/KFStoryGame/Classes/CashPickup_Story.uc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
class CashPickup_Story extends CashPickup ;
|
||||
|
||||
|
||||
|
||||
function GiveCashTo( Pawn Other )
|
||||
{
|
||||
// You all love the mental-mad typecasting XD
|
||||
if( !bDroppedCash )
|
||||
{
|
||||
/* the parent class was randomizing the cash amount by default values ... so whatever the LD set as 'cash amount' was being ignored .
|
||||
@fixme - This also appears to be *increasing* the amount of cash you gain from pickups the higher the difficulty level ... that doesn't sound right. */
|
||||
|
||||
CashAmount = ((rand(0.5 * CashAmount) + CashAmount) * (KFGameReplicationInfo(Level.GRI).GameDiff * 0.5)) * Max(KFGameType(Level.Game).GetNumPlayers(),1) ;
|
||||
}
|
||||
else if ( Other.PlayerReplicationInfo != none && DroppedBy.PlayerReplicationInfo != none &&
|
||||
((DroppedBy.PlayerReplicationInfo.Score + float(CashAmount)) / Other.PlayerReplicationInfo.Score) >= 0.50 &&
|
||||
PlayerController(DroppedBy) != none && KFSteamStatsAndAchievements(PlayerController(DroppedBy).SteamStatsAndAchievements) != none )
|
||||
{
|
||||
if ( Other.PlayerReplicationInfo != DroppedBy.PlayerReplicationInfo )
|
||||
{
|
||||
KFSteamStatsAndAchievements(PlayerController(DroppedBy).SteamStatsAndAchievements).AddDonatedCash(CashAmount);
|
||||
}
|
||||
}
|
||||
|
||||
if( Other.Controller!=None && Other.Controller.PlayerReplicationInfo!=none )
|
||||
{
|
||||
Other.Controller.PlayerReplicationInfo.Score += CashAmount;
|
||||
}
|
||||
AnnouncePickup(Other);
|
||||
SetRespawn();
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
RespawnTime = 0
|
||||
}
|
||||
65
kf_sources/KFStoryGame/Classes/Dialogue_EventListener.uc
Normal file
65
kf_sources/KFStoryGame/Classes/Dialogue_EventListener.uc
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Dialogue_EventListener
|
||||
--------------------------------------------------------------
|
||||
|
||||
Simple event listener actor spawned by KF_DialogueSpots.
|
||||
Notifies the dialogue spot that it can continue the dialogue chain
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Dialogue_EventListener extends Actor;
|
||||
|
||||
var KF_DialogueSpot DlgOwner;
|
||||
|
||||
var int AssociatedIndex;
|
||||
|
||||
function PostBeginPlay()
|
||||
{
|
||||
DlgOwner = KF_DialogueSpot(Owner);
|
||||
}
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
if(DlgOwner != none )
|
||||
{
|
||||
if(DlgOwner.bDebugDialogue)
|
||||
{
|
||||
log("----- DIALOGUE DEBUG ------ DialogueListener was triggered for Index "@AssociatedIndex@"Received event : "@DlgOwner.Dialogues[AssociatedIndex].Events.RequiredEvent@",triggered by : "@Other@" .. Proceeding ", 'Story_Debug');
|
||||
}
|
||||
|
||||
if(!DlgOwner.Dialogues[AssociatedIndex].bWasTriggered )
|
||||
{
|
||||
if(DlgOwner.bFinished)
|
||||
{
|
||||
DlgOwner.bFinished = false;
|
||||
}
|
||||
|
||||
DlgOwner.Dialogues[AssociatedIndex].bWasTriggered = true ;
|
||||
DlgOwner.CurrentMsgIdx = AssociatedIndex;
|
||||
DlgOwner.TraverseDialogue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Timer()
|
||||
{
|
||||
if(DlgOwner != none)
|
||||
{
|
||||
DlgOwner.OnDialogueDisplayComplete(AssociatedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bHidden=True
|
||||
CollisionRadius=1
|
||||
CollisionHeight=1
|
||||
bBlockZeroExtentTraces= False
|
||||
bBlockNonZeroExtentTraces= False
|
||||
RemoteRole = Role_None
|
||||
}
|
||||
49
kf_sources/KFStoryGame/Classes/Dummy_JoggingAttachment.uc
Normal file
49
kf_sources/KFStoryGame/Classes/Dummy_JoggingAttachment.uc
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
class Dummy_JoggingAttachment extends KFMeleeAttachment;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Mesh=none
|
||||
|
||||
MovementAnims(0)=JogF_Pipe
|
||||
MovementAnims(1)=JogB_Pipe
|
||||
MovementAnims(2)=JogL_Pipe
|
||||
MovementAnims(3)=JogR_Pipe
|
||||
CrouchAnims(0)=CHwalkF_Pipe
|
||||
CrouchAnims(1)=CHwalkB_Pipe
|
||||
CrouchAnims(2)=CHwalkL_Pipe
|
||||
CrouchAnims(3)=CHwalkR_Pipe
|
||||
AirStillAnim=JumpF_Mid
|
||||
AirAnims(0)=JumpF_Mid
|
||||
AirAnims(1)=JumpF_Mid
|
||||
AirAnims(2)=JumpL_Mid
|
||||
AirAnims(3)=JumpR_Mid
|
||||
TakeoffStillAnim=JumpF_Takeoff
|
||||
TakeoffAnims(0)=JumpF_Takeoff
|
||||
TakeoffAnims(1)=JumpF_Takeoff
|
||||
TakeoffAnims(2)=JumpL_Takeoff
|
||||
TakeoffAnims(3)=JumpR_Takeoff
|
||||
LandAnims(0)=JumpF_Land
|
||||
LandAnims(1)=JumpF_Land
|
||||
LandAnims(2)=JumpL_Land
|
||||
LandAnims(3)=JumpR_Land
|
||||
|
||||
TurnRightAnim=TurnR_Pipe
|
||||
TurnLeftAnim=TurnL_Pipe
|
||||
CrouchTurnRightAnim=CH_TurnR_Pipe
|
||||
CrouchTurnLeftAnim=CH_TurnL_Pipe
|
||||
IdleRestAnim=Idle_Pipe//Idle_Rest
|
||||
IdleCrouchAnim=CHIdle_Pipe
|
||||
IdleSwimAnim=Swim_Tread
|
||||
IdleWeaponAnim=Idle_Pipe//Idle_Rifle
|
||||
IdleHeavyAnim=Idle_Pipe//Idle_Biggun
|
||||
IdleRifleAnim=Idle_Pipe//Idle_Rifle
|
||||
IdleChatAnim=Idle_Pipe
|
||||
FireAnims(0)=Attack1_Pipe
|
||||
FireAnims(1)=Attack2_Pipe
|
||||
FireAnims(2)=Attack3_Pipe
|
||||
FireAnims(3)=Attack4_Pipe
|
||||
FireAltAnims(0)=Attack1_Pipe
|
||||
FireAltAnims(1)=Attack2_Pipe
|
||||
FireAltAnims(2)=Attack3_Pipe
|
||||
FireAltAnims(3)=Attack4_Pipe
|
||||
}
|
||||
39
kf_sources/KFStoryGame/Classes/Dummy_JoggingWeapon.uc
Normal file
39
kf_sources/KFStoryGame/Classes/Dummy_JoggingWeapon.uc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Dummy_JoggingWeapon
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
This is basically just a dummy inventory class that KF pawns
|
||||
can hold when they are supposed to not be holding any weapon.
|
||||
It's necessary since there isn't any real support in the KF Pawn
|
||||
Animation / Weapon attachment code for that.
|
||||
|
||||
While carrying this weapon your dude looks like he is Jogging with
|
||||
his arms at his sides.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class Dummy_JoggingWeapon extends KFWeapon
|
||||
HideDropdown;
|
||||
|
||||
|
||||
simulated function String GetHumanReadableName()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Weight=0
|
||||
|
||||
FireModeClass(0)=Class'KFMod.NoFire'
|
||||
FireModeClass(1)=Class'KFMod.NoFire'
|
||||
|
||||
InventoryGroup = 0
|
||||
bKFNeverThrow=True
|
||||
AttachmentClass = class 'Dummy_JoggingAttachment'
|
||||
}
|
||||
41
kf_sources/KFStoryGame/Classes/Emitter_BreakerExplosion.uc
Normal file
41
kf_sources/KFStoryGame/Classes/Emitter_BreakerExplosion.uc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
class Emitter_BreakerExplosion extends MetalHitEmitter;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter33
|
||||
UseDirectionAs=PTDU_UpAndNormal
|
||||
UseCollision=True
|
||||
UseColorScale=True
|
||||
FadeOut=True
|
||||
FadeIn=True
|
||||
RespawnDeadParticles=False
|
||||
UseSizeScale=True
|
||||
UseRegularSizeScale=False
|
||||
UniformSize=True
|
||||
ScaleSizeXByVelocity=True
|
||||
AutomaticInitialSpawning=False
|
||||
Acceleration=(Z=-210.000000)
|
||||
DampingFactorRange=(X=(Min=0.500000,Max=0.500000),Y=(Min=0.500000,Max=0.500000),Z=(Min=0.500000,Max=0.500000))
|
||||
ColorScale(0)=(Color=(B=255,G=255,R=187))
|
||||
ColorScale(1)=(RelativeTime=0.214286,Color=(G=103,R=206,A=255))
|
||||
ColorScale(2)=(RelativeTime=0.439286,Color=(B=100,G=177,R=255,A=255))
|
||||
ColorScale(3)=(RelativeTime=1.000000,Color=(G=103,R=206,A=255))
|
||||
ColorScale(4)=(RelativeTime=1.000000,Color=(G=103,R=206,A=255))
|
||||
ColorScale(5)=(RelativeTime=1.000000,Color=(R=128,A=255))
|
||||
ColorScale(6)=(RelativeTime=1.000000)
|
||||
ColorScale(7)=(RelativeTime=1.000000)
|
||||
FadeOutStartTime=0.336000
|
||||
FadeInEndTime=0.064000
|
||||
MaxParticles=100
|
||||
Name="SpriteEmitter33"
|
||||
SizeScale(0)=(RelativeSize=1.000000)
|
||||
SizeScale(1)=(RelativeTime=1.000000,RelativeSize=0.250000)
|
||||
StartSizeRange=(X=(Min=3.000000,Max=10.000000),Y=(Min=5000.000000,Max=5000.000000),Z=(Min=5000.000000,Max=5000.000000))
|
||||
ScaleSizeByVelocityMultiplier=(X=0.010000,Y=0.010000)
|
||||
InitialParticlesPerSecond=5000.000000
|
||||
Texture=Texture'KFX.KFSparkHead'
|
||||
LifetimeRange=(Min=1.500000,Max=1.500000)
|
||||
StartVelocityRange=(X=(Min=-200.000000,Max=200.000000),Y=(Min=-200.000000,Max=200.000000),Z=(Min=-200.000000,Max=200.000000))
|
||||
End Object
|
||||
Emitters(0)=SpriteEmitter'SpriteEmitter33'
|
||||
}
|
||||
39
kf_sources/KFStoryGame/Classes/Emitter_CoinExplosion.uc
Normal file
39
kf_sources/KFStoryGame/Classes/Emitter_CoinExplosion.uc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
class Emitter_CoinExplosion extends Emitter;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Begin Object Class=MeshEmitter Name=MeshEmitter0
|
||||
StaticMesh=StaticMesh'KF_Swansong_SM.Lootbag.Coin'
|
||||
UseParticleColor=True
|
||||
UseCollision=True
|
||||
UseMaxCollisions=True
|
||||
UseColorScale=True
|
||||
RespawnDeadParticles=False
|
||||
SpinParticles=True
|
||||
DampRotation=True
|
||||
AutomaticInitialSpawning=False
|
||||
Acceleration=(Z=-215.000000)
|
||||
DampingFactorRange=(X=(Min=0.500000,Max=0.500000),Y=(Min=0.500000,Max=0.500000),Z=(Min=0.500000,Max=0.500000))
|
||||
MaxCollisions=(Min=7.000000,Max=7.000000)
|
||||
ColorScale(0)=(Color=(G=255,R=255))
|
||||
ColorScale(1)=(RelativeTime=1.000000,Color=(G=255,R=255))
|
||||
FadeOutStartTime=1.000000
|
||||
MaxParticles=30
|
||||
StartLocationRange=(X=(Min=-3.000000,Max=3.000000),Y=(Min=-3.000000,Max=3.000000),Z=(Max=10.000000))
|
||||
UseRotationFrom=PTRS_Normal
|
||||
SpinsPerSecondRange=(X=(Min=0.200000,Max=0.800000),Y=(Min=0.200000,Max=0.800000),Z=(Min=0.200000,Max=0.800000))
|
||||
StartSpinRange=(X=(Max=16000.000000),Y=(Max=16000.000000),Z=(Max=16000.000000))
|
||||
RotationDampingFactorRange=(X=(Min=0.250000,Max=0.500000),Y=(Min=0.250000,Max=0.500000),Z=(Min=0.250000,Max=0.500000))
|
||||
StartSizeRange=(X=(Min=0.600000,Max=0.600000),Y=(Min=0.600000,Max=0.600000))
|
||||
InitialParticlesPerSecond=10000.000000
|
||||
StartVelocityRange=(X=(Min=-30.000000,Max=30.000000),Y=(Min=-30.000000,Max=30.000000),Z=(Min=50.000000,Max=150.000000))
|
||||
End Object
|
||||
Emitters(0)=MeshEmitter'MeshEmitter0'
|
||||
|
||||
// Default non particle properties
|
||||
|
||||
bNoDelete=FALSE
|
||||
DrawScale=0.500000
|
||||
AmbientGlow=48
|
||||
bUnlit=False
|
||||
}
|
||||
60
kf_sources/KFStoryGame/Classes/Emitter_VialBreak.uc
Normal file
60
kf_sources/KFStoryGame/Classes/Emitter_VialBreak.uc
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
class Emitter_VialBreak extends Emitter;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
// Glass
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter75
|
||||
FadeOut=True
|
||||
RespawnDeadParticles=False
|
||||
UseRevolution=True
|
||||
SpinParticles=True
|
||||
UniformSize=True
|
||||
AutomaticInitialSpawning=False
|
||||
UseRandomSubdivision=True
|
||||
Acceleration=(Z=-150.000000)
|
||||
FadeOutStartTime=1.000000
|
||||
MaxParticles=6
|
||||
StartLocationRange=(X=(Min=-5.000000,Max=5.000000),Y=(Min=-5.000000,Max=5.000000),Z=(Min=5.000000,Max=10.000000))
|
||||
SpinsPerSecondRange=(X=(Min=0.100000,Max=0.500000),Y=(Min=0.100000,Max=0.500000))
|
||||
StartSpinRange=(X=(Max=16000.000000),Y=(Max=16000.000000),Z=(Max=16000.000000))
|
||||
StartSizeRange=(X=(Min=5.000000,Max=10.000000),Y=(Min=5.000000,Max=10.000000))
|
||||
InitialParticlesPerSecond=1000.000000
|
||||
Texture=Texture'Effects_Tex.BulletHits.brokenglass_chunks_01'
|
||||
TextureUSubdivisions=2
|
||||
TextureVSubdivisions=2
|
||||
LifetimeRange=(Min=1.500000,Max=1.500000)
|
||||
StartVelocityRange=(X=(Min=-30.000000,Max=30.000000),Y=(Min=-30.000000,Max=30.000000),Z=(Min=45.000000,Max=55.000000))
|
||||
End Object
|
||||
Emitters(0)=SpriteEmitter'SpriteEmitter75'
|
||||
// DNA Goo
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter76
|
||||
FadeOut=True
|
||||
RespawnDeadParticles=False
|
||||
SpinParticles=True
|
||||
UseSizeScale=True
|
||||
UseRegularSizeScale=False
|
||||
UniformSize=True
|
||||
AutomaticInitialSpawning=False
|
||||
UseRandomSubdivision=True
|
||||
Acceleration=(Z=-100.000000)
|
||||
FadeOutStartTime=1.000000
|
||||
MaxParticles=5
|
||||
StartLocationRange=(X=(Min=-5.000000,Max=5.000000),Y=(Min=-5.000000,Max=5.000000),Z=(Min=-10.000000,Max=0.000000))
|
||||
UseRotationFrom=PTRS_Normal
|
||||
StartSpinRange=(X=(Max=16000.000000),Y=(Max=16000.000000))
|
||||
SizeScale(0)=(RelativeSize=1.000000)
|
||||
SizeScale(1)=(RelativeTime=1.000000,RelativeSize=10.000000)
|
||||
StartSizeRange=(X=(Min=5.000000,Max=5.000000),Y=(Min=5.000000,Max=5.000000))
|
||||
InitialParticlesPerSecond=10000.000000
|
||||
DrawStyle=PTDS_Modulated
|
||||
Texture=Texture'kf_fx_trip_t.Misc.Vomit_Splat_E'
|
||||
TextureUSubdivisions=1
|
||||
TextureVSubdivisions=1
|
||||
LifetimeRange=(Min=1.500000,Max=1.500000)
|
||||
StartVelocityRange=(X=(Min=-20.000000,Max=20.000000),Y=(Min=-20.000000,Max=20.000000),Z=(Min=15.000000,Max=25.000000))
|
||||
End Object
|
||||
Emitters(1)=SpriteEmitter'SpriteEmitter76'
|
||||
|
||||
bNoDelete=False
|
||||
}
|
||||
|
||||
2058
kf_sources/KFStoryGame/Classes/HUD_StoryMode.uc
Normal file
2058
kf_sources/KFStoryGame/Classes/HUD_StoryMode.uc
Normal file
File diff suppressed because it is too large
Load diff
16
kf_sources/KFStoryGame/Classes/Inv_MaintenanceKeyCard.uc
Normal file
16
kf_sources/KFStoryGame/Classes/Inv_MaintenanceKeyCard.uc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Inv_MaintenanceKeyCard
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Inv_MaintenanceKeyCard extends KF_StoryInventoryItem;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bDropFromCameraLoc=true
|
||||
AttachmentClass = none;
|
||||
PickupClass = class 'Pickup_MaintenanceKeyCard'
|
||||
CarriedMaterial = Texture 'KF_Swansong_Tex.Icons.Keycard_Icon_64'
|
||||
GroundMaterial = Colormodifier 'FrightYard_T.RemotePickupGroundIco_cm'
|
||||
}
|
||||
20
kf_sources/KFStoryGame/Classes/Inv_Nitroglycerin.uc
Normal file
20
kf_sources/KFStoryGame/Classes/Inv_Nitroglycerin.uc
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Inv_Nitroglycerin
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Inv_Nitroglycerin extends KF_StoryInventoryItem;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bDropFromCameraLoc=true
|
||||
AttachmentClass = none;
|
||||
CarriedMaterial = Texture 'KF_Swansong_Tex.Icons.Nitroglycerin_Icon_64'
|
||||
GroundMaterial = Colormodifier 'FrightYard_T.RemotePickupGroundIco_cm'
|
||||
|
||||
bUseForcedGroundSpeed = true
|
||||
ForcedGroundSpeed =120.0
|
||||
|
||||
PickupClass = class 'Pickup_Nitroglycerin'
|
||||
}
|
||||
16
kf_sources/KFStoryGame/Classes/Inv_PatriarchEyeball.uc
Normal file
16
kf_sources/KFStoryGame/Classes/Inv_PatriarchEyeball.uc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Inv_PatriarchEyeBall
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Inv_PatriarchEyeball extends KF_StoryInventoryItem;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bDropFromCameraLoc=true
|
||||
AttachmentClass = none;
|
||||
PickupClass = class 'Pickup_PatriarchEyeBall'
|
||||
CarriedMaterial = Texture 'KF_Swansong_Tex.Icons.Eyeball_Icon_64'
|
||||
GroundMaterial = Colormodifier 'FrightYard_T.RemotePickupGroundIco_cm'
|
||||
}
|
||||
16
kf_sources/KFStoryGame/Classes/Inv_Thermite.uc
Normal file
16
kf_sources/KFStoryGame/Classes/Inv_Thermite.uc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Inv_Thermite
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Inv_Thermite extends KF_StoryInventoryItem;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bDropFromCameraLoc=true
|
||||
AttachmentClass = none;
|
||||
PickupClass = class 'Pickup_Thermite'
|
||||
CarriedMaterial = Texture 'KF_Swansong_Tex.Icons.Thermite_Icon_64'
|
||||
GroundMaterial = Colormodifier 'FrightYard_T.RemotePickupGroundIco_cm'
|
||||
}
|
||||
23
kf_sources/KFStoryGame/Classes/KFAmmoPickup_Story.uc
Normal file
23
kf_sources/KFStoryGame/Classes/KFAmmoPickup_Story.uc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KFAmmoPickup_Story
|
||||
--------------------------------------------------------------
|
||||
|
||||
AmmoPickup actors tailored to Story missions. Refills specific
|
||||
types of weapons.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KFAmmoPickup_Story extends KFAmmoPickup;
|
||||
|
||||
state Pickup
|
||||
{
|
||||
// When touched by an actor.
|
||||
function Touch(Actor Other)
|
||||
{
|
||||
Super(Ammo).Touch(Other);
|
||||
}
|
||||
}
|
||||
6
kf_sources/KFStoryGame/Classes/KFHintmanager_Story.uc
Normal file
6
kf_sources/KFStoryGame/Classes/KFHintmanager_Story.uc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class KFHintmanager_Story extends KFHintManager;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Hints(42)=(type=61,priority=20,delay=1,title="Optional Missions",hint="You have just received an optional mission. Completing it will give give you a cash bonus. To start the mission proceed to the Mission area on your HUD")
|
||||
}
|
||||
609
kf_sources/KFStoryGame/Classes/KFHumanPawn_Story.uc
Normal file
609
kf_sources/KFStoryGame/Classes/KFHumanPawn_Story.uc
Normal file
|
|
@ -0,0 +1,609 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KFHumanPawn_Story
|
||||
--------------------------------------------------------------
|
||||
|
||||
Custom Pawn class for use in Killing Floor 'Story' maps.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KFHumanPawn_Story extends KFHumanPawn ;
|
||||
|
||||
/* true if this pawn has had its currently held gear stored at a checkpoint */
|
||||
var bool bSavedLoadout;
|
||||
|
||||
/* Pawn is currently holding a KF_StoryInventoryItem actor */
|
||||
var bool bHasStoryItem;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if ( bNetDirty && (Role == Role_Authority) )
|
||||
bHasStoryItem;
|
||||
}
|
||||
simulated function Fire( optional float F )
|
||||
{
|
||||
local Controller C;
|
||||
|
||||
for ( C = Level.ControllerList; C != None; C = C.NextController )
|
||||
{
|
||||
C.ReceiveWarning(self,0,vector(Rotation));
|
||||
}
|
||||
|
||||
Super.Fire(F);
|
||||
}
|
||||
|
||||
function bool DoJump( bool bUpdating )
|
||||
{
|
||||
local float JumpModifier;
|
||||
|
||||
JumpModifier = GetJumpZModifier();
|
||||
|
||||
/* Also ramp up the allowed fallspeed so larger jumps dont instantly kill us */
|
||||
MaxFallSpeed = default.MaxFallSpeed * JumpModifier;
|
||||
JumpZ = default.JumpZ * JumpModifier ;
|
||||
|
||||
|
||||
|
||||
return Super.DoJump(bUpdating);
|
||||
}
|
||||
|
||||
simulated function float GetJumpZModifier()
|
||||
{
|
||||
local inventory I;
|
||||
local float Modifier;
|
||||
local KF_StoryInventoryItem Storyinv;
|
||||
|
||||
Modifier = 1.f;
|
||||
|
||||
for ( I = Inventory; I != none; I = I.Inventory )
|
||||
{
|
||||
StoryInv = KF_StoryInventoryItem(I);
|
||||
if(StoryInv != none)
|
||||
{
|
||||
Modifier *= StoryInv.JumpZModifier;
|
||||
}
|
||||
}
|
||||
|
||||
return Modifier;
|
||||
}
|
||||
|
||||
function SetHasStoryItem( bool bHasItem )
|
||||
{
|
||||
bHasStoryItem = bHasItem;
|
||||
}
|
||||
|
||||
simulated event ModifyVelocity(float DeltaTime, vector OldVelocity)
|
||||
{
|
||||
local inventory I;
|
||||
local KF_StoryInventoryItem Storyinv;
|
||||
|
||||
Super.ModifyVelocity(DeltaTime,OldVelocity);
|
||||
|
||||
for ( I = Inventory; I != none; I = I.Inventory )
|
||||
{
|
||||
StoryInv = KF_StoryInventoryItem(I);
|
||||
if(StoryInv != none && StoryInv.bUseForcedGroundSpeed)
|
||||
{
|
||||
GroundSpeed = StoryInv.ForcedGroundSpeed ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
super.TakeDamage( Damage, InstigatedBY, Hitlocation, Momentum, damageType, HitIndex );
|
||||
|
||||
// HandleStoryAchievements is only used for Steamland. In fact, it screws up KFO-Transit!
|
||||
if( class'KFGameType'.static.GetCurrentMapName(Level) ~= "KFO-Steamland" )
|
||||
{
|
||||
HandleStoryAchievements();
|
||||
}
|
||||
}
|
||||
|
||||
function HandleStoryAchievements()
|
||||
{
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
if ( bHasStoryItem )
|
||||
{
|
||||
KFGRI = KFGameReplicationInfo( Level.GRI );
|
||||
if( KFGRI != none )
|
||||
{
|
||||
KFGRI.bObjectiveAchievementFailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bool AddInventory( inventory NewItem )
|
||||
{
|
||||
if( !super.AddInventory(NewItem) )
|
||||
return false;
|
||||
|
||||
if( KF_StoryInventoryItem(NewItem) != none )
|
||||
{
|
||||
CurrentWeight += KF_StoryInventoryItem(NewItem).Weight;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove Item from this pawn's inventory, if it exists.
|
||||
function DeleteInventory( inventory Item )
|
||||
{
|
||||
local Inventory I;
|
||||
local bool bFoundItem;
|
||||
|
||||
if ( Role != ROLE_Authority )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( I = Inventory; I != none; I = I.Inventory )
|
||||
{
|
||||
if ( I == Item )
|
||||
{
|
||||
bFoundItem = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bFoundItem )
|
||||
{
|
||||
if ( KF_StoryInventoryItem(Item) != none )
|
||||
{
|
||||
CurrentWeight -= KF_StoryInventoryItem(Item).Weight;
|
||||
}
|
||||
}
|
||||
|
||||
super.DeleteInventory(Item);
|
||||
}
|
||||
|
||||
/* Returns true if this pawn is able to hold a weapon of the supplied type */
|
||||
simulated function bool AllowHoldWeapon(Weapon InWeapon)
|
||||
{
|
||||
local bool Result;
|
||||
local Inventory Inv;
|
||||
local KF_StoryInventoryItem StoryInv;
|
||||
|
||||
Result = true;
|
||||
|
||||
/* Query our inventory items to see if they restrict any weaponry we're holding */
|
||||
for ( Inv=Inventory; Inv!=None; Inv=Inv.Inventory )
|
||||
{
|
||||
StoryInv = KF_StoryInventoryItem(Inv);
|
||||
if(StoryInv != none)
|
||||
{
|
||||
if(!StoryInv.AllowHoldWeapon(InWeapon))
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// log("*********************************************");
|
||||
// log("Allow Hold Weapon of Type : "@InWeapon@" - "@Result);
|
||||
// log("*********************************************");
|
||||
|
||||
if(!Result)
|
||||
{
|
||||
PlayerController(Controller).ReceiveLocalizedMessage(Class'KFMainMessages',5,,,InWeapon);
|
||||
}
|
||||
|
||||
Return Result;
|
||||
}
|
||||
|
||||
|
||||
simulated function Weapon FindUseableWeaponFor(KF_StoryInventoryItem I)
|
||||
{
|
||||
local Inventory Inv;
|
||||
local Weapon UseableWeap;
|
||||
local Dummy_JoggingWeapon DummyWeap;
|
||||
|
||||
for( Inv=Inventory; Inv!=None; Inv=Inv.Inventory )
|
||||
{
|
||||
if(Weapon(inv) != none && I.AllowHoldWeapon(Weapon(Inv),true))
|
||||
{
|
||||
UseableWeap = Weapon(Inv);
|
||||
}
|
||||
}
|
||||
|
||||
if(UseableWeap == none )
|
||||
{
|
||||
DummyWeap = Dummy_JoggingWeapon(FindInventoryType(class 'Dummy_JoggingWeapon'));
|
||||
if(DummyWeap != none)
|
||||
{
|
||||
UseableWeap = DummyWeap ;
|
||||
}
|
||||
}
|
||||
|
||||
log("Found useable weapon : "@UseableWeap);
|
||||
return UseableWeap;
|
||||
}
|
||||
|
||||
/* Cache a list of equipment the pawn was carrying at the time of his death */
|
||||
simulated function SaveLoadOut()
|
||||
{
|
||||
local Inventory Inv;
|
||||
local int Count;
|
||||
local KFPlayerController_Story PC;
|
||||
|
||||
PC = KFPlayerController_Story(Controller);
|
||||
if(PC == none )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save equipment that we're holding */
|
||||
for( Inv=Inventory; Inv!=None ;Inv=Inv.Inventory )
|
||||
{
|
||||
if(KFWeapon(Inv) != none)
|
||||
{
|
||||
PC.SavedLoadOut[Count] = string(Inv.class) ;
|
||||
PC.SavedAmmo[Count] = Weapon(Inv).AmmoAmount(0);
|
||||
PC.SavedMagAmmo[Count] = KFWeapon(Inv).MagAmmoRemaining;
|
||||
|
||||
Count ++ ;
|
||||
}
|
||||
}
|
||||
|
||||
PC.SavedHealth = Health;
|
||||
PC.SavedArmor = ShieldStrength ;
|
||||
}
|
||||
|
||||
|
||||
function bool RetrieveSavedLoadOut(Controller C)
|
||||
{
|
||||
local int i, Index;
|
||||
local KFPlayerController_Story PC;
|
||||
|
||||
PC = KFPLayerController_Story(C);
|
||||
if(PC != none && PC.CurrentCheckPoint != none)
|
||||
{
|
||||
/* Add Saved equipment from our controller .. */
|
||||
for(i = 0 ; i < Min(PC.SavedLoadOut.length,ArrayCount(RequiredEquipment)) ; i ++)
|
||||
{
|
||||
if(RequiredEquipment[i] == "" && PC.SavedLoadOut[i] != "")
|
||||
{
|
||||
RequiredEquipment[i] = PC.SavedLoadOut[i] ;
|
||||
Index ++ ;
|
||||
}
|
||||
}
|
||||
|
||||
return Index > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function AddDefaultInventory()
|
||||
{
|
||||
local KFLevelRules_Story StoryRules;
|
||||
local int i,InvCount;
|
||||
local Inventory Inv;
|
||||
local KFPlayerController_Story SPC;
|
||||
local bool bUseCheckPointGear;
|
||||
local float MaxAmmo,CurrentAmmo;
|
||||
|
||||
/* Clear pawn equipment defaults */
|
||||
for(i = 0 ; i < ArrayCount(RequiredEquipment) ; i ++)
|
||||
{
|
||||
RequiredEquipment[i] = "" ;
|
||||
}
|
||||
|
||||
/* Base gear should fill from the level rules */
|
||||
Level.Game.AddGameSpecificInventory(self);
|
||||
|
||||
/* next we Add saved gear - stuff we were carrying when we died */
|
||||
|
||||
bUseCheckPointGear = RetrieveSavedLoadOut(Controller);
|
||||
|
||||
Super(UnrealPawn).AddDefaultInventory();
|
||||
|
||||
/* next add perk specific gear - on request */
|
||||
if(KFStoryGameInfo(Level.Game) != none)
|
||||
{
|
||||
StoryRules = KFStoryGameInfo(Level.Game).StoryRules ;
|
||||
if(StoryRules != none && StoryRules.bAllowPerkStartingWeaps)
|
||||
{
|
||||
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
||||
{
|
||||
KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.AddDefaultInventory(KFPlayerReplicationInfo(PlayerReplicationInfo), self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bUseCheckPointGear)
|
||||
{
|
||||
/* restore saved ammo values from our last checkpoint .. */
|
||||
SPC = KFPlayerController_Story(Controller);
|
||||
if(SPC != none)
|
||||
{
|
||||
for( Inv=Inventory; Inv!=None ;Inv=Inv.Inventory )
|
||||
{
|
||||
if(Weapon(Inv) != none)
|
||||
{
|
||||
Weapon(Inv).GetAmmoCount(MaxAmmo,CurrentAmmo);
|
||||
Weapon(Inv).ConsumeAmmo(0,MaxAmmo,true);
|
||||
|
||||
Weapon(Inv).AddAmmo(SPC.SavedAmmo[InvCount],0);
|
||||
KFWeapon(Inv).MagAmmoRemaining = SPC.SavedMagAmmo[InvCount];
|
||||
|
||||
InvCount ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Tick(float DeltaTime)
|
||||
{
|
||||
local KF_StoryPRI PRI;
|
||||
|
||||
Super.Tick(DeltaTime);
|
||||
|
||||
/* Replicated Location stuff - for tracking this pawn's position to display icons when its not relevant */
|
||||
|
||||
PRI = KF_StoryPRI(PlayerReplicationInfo) ;
|
||||
if(PRI != none && PRI.GetFloatingIconMat() != none)
|
||||
{
|
||||
if(Role == Role_Authority) // server authoritative
|
||||
{
|
||||
if(PRI.GetOwnerPawn() != self)
|
||||
{
|
||||
PRI.SetOwnerPawn(self);
|
||||
PRI.NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
|
||||
KF_StoryPRI(PlayerReplicationInfo).SetReplicatedPawnLoc(GetHoverIconPosition());
|
||||
}
|
||||
else // simulated proxy.
|
||||
{
|
||||
if(bDeleteMe || bPendingDelete)
|
||||
{
|
||||
PRI.SetOwnerPawn(none);
|
||||
PRI.NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* position to render hovering icons at */
|
||||
simulated function vector GetHoverIconPosition()
|
||||
{
|
||||
return Location + Vect(0,0,1)*CollisionHeight ;
|
||||
}
|
||||
|
||||
/* Fixing a problem where Perk-Less players dont get charged for ammo */
|
||||
|
||||
function bool ServerBuyAmmo( Class<Ammunition> AClass, bool bOnlyClip )
|
||||
{
|
||||
local Inventory I;
|
||||
local float Price;
|
||||
local Ammunition AM;
|
||||
local KFWeapon KW;
|
||||
local int c;
|
||||
local float UsedMagCapacity;
|
||||
local class<KFVeterancyTypes> PlayerVeterancy;
|
||||
|
||||
if ( !CanBuyNow() || AClass == None )
|
||||
{
|
||||
SetTraderUpdate();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab Players Veterancy for quick reference
|
||||
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none &&
|
||||
KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
||||
{
|
||||
PlayerVeterancy = KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerVeterancy = class'KFVeterancyTypes';
|
||||
}
|
||||
|
||||
|
||||
for ( I=Inventory; I != none; I=I.Inventory )
|
||||
{
|
||||
if ( I.Class == AClass )
|
||||
{
|
||||
AM = Ammunition(I);
|
||||
}
|
||||
else if ( KW == None && KFWeapon(I) != None && (Weapon(I).AmmoClass[0] == AClass || Weapon(I).AmmoClass[1] == AClass) )
|
||||
{
|
||||
KW = KFWeapon(I);
|
||||
}
|
||||
}
|
||||
|
||||
if ( KW == none || AM == none )
|
||||
{
|
||||
SetTraderUpdate();
|
||||
return false;
|
||||
}
|
||||
|
||||
AM.MaxAmmo = AM.default.MaxAmmo;
|
||||
|
||||
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && PlayerVeterancy != none )
|
||||
{
|
||||
AM.MaxAmmo = int(float(AM.MaxAmmo) * PlayerVeterancy.static.AddExtraAmmoFor(KFPlayerReplicationInfo(PlayerReplicationInfo), AClass));
|
||||
}
|
||||
|
||||
if ( AM.AmmoAmount >= AM.MaxAmmo )
|
||||
{
|
||||
SetTraderUpdate();
|
||||
return false;
|
||||
}
|
||||
|
||||
Price = class<KFWeaponPickup>(KW.PickupClass).default.AmmoCost * PlayerVeterancy.static.GetAmmoCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), KW.PickupClass); // Clip price.
|
||||
|
||||
if ( KW.bHasSecondaryAmmo && AClass == KW.FireModeClass[1].default.AmmoClass )
|
||||
{
|
||||
UsedMagCapacity = 1; // Secondary Mags always have a Mag Capacity of 1? KW.default.SecondaryMagCapacity;
|
||||
}
|
||||
else
|
||||
{
|
||||
UsedMagCapacity = KW.default.MagCapacity;
|
||||
}
|
||||
|
||||
if( KW.PickupClass == class'HuskGunPickup' )
|
||||
{
|
||||
UsedMagCapacity = class<HuskGunPickup>(KW.PickupClass).default.BuyClipSize;
|
||||
}
|
||||
|
||||
if ( bOnlyClip )
|
||||
{
|
||||
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && PlayerVeterancy != none )
|
||||
{
|
||||
if( KW.PickupClass == class'HuskGunPickup' )
|
||||
{
|
||||
c = UsedMagCapacity * PlayerVeterancy.static.AddExtraAmmoFor(KFPlayerReplicationInfo(PlayerReplicationInfo), AM.Class);
|
||||
}
|
||||
else
|
||||
{
|
||||
c = UsedMagCapacity * PlayerVeterancy.static.GetMagCapacityMod(KFPlayerReplicationInfo(PlayerReplicationInfo), KW);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = UsedMagCapacity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = (AM.MaxAmmo-AM.AmmoAmount);
|
||||
}
|
||||
|
||||
Price = int(float(c) / UsedMagCapacity * Price);
|
||||
|
||||
if ( PlayerReplicationInfo.Score < Price ) // Not enough CASH (so buy the amount you CAN buy).
|
||||
{
|
||||
c *= (PlayerReplicationInfo.Score/Price);
|
||||
|
||||
if ( c == 0 )
|
||||
{
|
||||
SetTraderUpdate();
|
||||
return false; // Couldn't even afford 1 bullet.
|
||||
}
|
||||
|
||||
AM.AddAmmo(c);
|
||||
PlayerReplicationInfo.Score = Max(PlayerReplicationInfo.Score - (float(c) / UsedMagCapacity * Price), 0);
|
||||
|
||||
SetTraderUpdate();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PlayerReplicationInfo.Score = int(PlayerReplicationInfo.Score-Price);
|
||||
AM.AddAmmo(c);
|
||||
|
||||
SetTraderUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Drops All Story Items
|
||||
simulated function InternalTossCarriedItems()
|
||||
{
|
||||
local Inventory Inv, NextInv;
|
||||
local Vector X,Y,Z;
|
||||
local Vector TossDir;
|
||||
local float TossSpeed;
|
||||
local vector DropLoc;
|
||||
|
||||
GetAxes(Rotation,X,Y,Z);
|
||||
|
||||
|
||||
TossSpeed = 250.f;
|
||||
DropLoc = Location + 0.8 * CollisionRadius * X - 0.5 * CollisionRadius * Y;
|
||||
|
||||
// Throws all your story items
|
||||
for( Inv=Inventory; Inv!=None; Inv=NextInv )
|
||||
{
|
||||
NextInv = Inv.Inventory;
|
||||
TossDir = VRand();
|
||||
TossStoryItem( Inv, TossDir, TossSpeed, DropLoc );
|
||||
}
|
||||
|
||||
// Throws your weapon
|
||||
super.InternalTossCarriedItems();
|
||||
}
|
||||
|
||||
// Drops a single story item
|
||||
simulated function TossSingleCarriedItem()
|
||||
{
|
||||
local Inventory Inv;
|
||||
local Vector X,Y,Z;
|
||||
local Vector TossDir;
|
||||
local float TossSpeed;
|
||||
local vector DropLoc;
|
||||
|
||||
GetAxes(Rotation,X,Y,Z);
|
||||
|
||||
TossDir = vector(Rotation);
|
||||
TossSpeed = 250.f;
|
||||
DropLoc = Location + 0.8 * CollisionRadius * X - 0.5 * CollisionRadius * Y;
|
||||
|
||||
for( Inv=Inventory; Inv!=None; Inv=Inv.Inventory)
|
||||
{
|
||||
TossStoryItem( Inv, TossDir, TossSpeed, DropLoc );
|
||||
}
|
||||
}
|
||||
|
||||
simulated function TossStoryItem( Inventory Inv, Vector TossDir, float TossSpeed, vector DropLoc )
|
||||
{
|
||||
local KF_StoryinventoryItem StoryInv;
|
||||
if(Inv.IsThrowable())
|
||||
{
|
||||
StoryInv = KF_StoryInventoryItem(Inv);
|
||||
if(StoryInv != none)
|
||||
{
|
||||
if(StoryInv.bDropFromCameraLoc)
|
||||
{
|
||||
TossDir = Vector(GetViewRotation());
|
||||
if(PlayerController(Controller) != none)
|
||||
{
|
||||
DropLoc = PlayerController(Controller).CalcViewLocation;
|
||||
}
|
||||
}
|
||||
|
||||
TossSpeed = StoryInv.Pickup_TossVelocity;
|
||||
}
|
||||
Inv.Velocity = TossDir * TossSpeed;
|
||||
Inv.DropFrom(DropLoc);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============ AI - Monster threat assessment functionality ==============================
|
||||
Clamped from -1 to 100, where 100 is the most threatening ==================================
|
||||
===========================================================================================*/
|
||||
|
||||
function float AssessThreatTo(KFMonsterController Monster, optional bool CheckDistance)
|
||||
{
|
||||
local float ThreatRating;
|
||||
local Inventory CurInv;
|
||||
local KF_StoryInventoryItem StoryInv;
|
||||
|
||||
ThreatRating = Super.AssessThreatTo(Monster,CheckDistance);
|
||||
|
||||
/* Factor in story Items which adjust your desirability to ZEDs */
|
||||
for ( CurInv = Inventory; CurInv != none; CurInv = CurInv.Inventory )
|
||||
{
|
||||
StoryInv = KF_StoryInventoryItem(CurInv);
|
||||
if(StoryInv != none)
|
||||
{
|
||||
ThreatRating *= StoryInv.AIThreatModifier ;
|
||||
}
|
||||
}
|
||||
|
||||
return ThreatRating;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
152
kf_sources/KFStoryGame/Classes/KFLevelRules_Story.uc
Normal file
152
kf_sources/KFStoryGame/Classes/KFLevelRules_Story.uc
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KFLevelRules_Story
|
||||
--------------------------------------------------------------
|
||||
|
||||
Extended LevelRules info for use in 'Story' style missions .
|
||||
Can modify player starting equipment, health, cash , etc.
|
||||
Also stores a list of Objectives the player must complete to
|
||||
be victorious.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KFLevelRules_Story extends KFLevelRules
|
||||
hidecategories(Sound,Events)
|
||||
dependson(KFStoryGameInfo) ;
|
||||
|
||||
#exec OBJ LOAD FILE=KFStoryGame_Tex.utx
|
||||
|
||||
/* should the first objective in the StoryObjectives array activate as soon as the match begins ? */
|
||||
var(Rules_Objectives) bool bAutoStartObjectives;
|
||||
|
||||
/* Amount of dosh to start players out with in story mode */
|
||||
var(Rules_Cash) int StartingCashSum;
|
||||
|
||||
/* A modifier for the amount of cash players receive from killing zombies. ie. at 0.f they will not receive anything */
|
||||
var(Rules_Cash) float CashReward_ZEDKills_Modifier;
|
||||
|
||||
/* A modifier for the amount of cash players lose when they die */
|
||||
var(Rules_Cash) float CashPenalty_Death_Modifier;
|
||||
|
||||
/* absolute maximum number of zombies we can have in this story map at one time */
|
||||
var(Rules_Monsters) int MaxEnemiesAtOnce;
|
||||
|
||||
/* should the game kill off ZEDs which haven't been seen by players for a while? */
|
||||
var(Rules_Monsters) bool bAutoKillStragglers;
|
||||
|
||||
/* Auto Kill threshold if bAutoKilLStragglers is true */
|
||||
var(Rules_Monsters) int MaxStragglers;
|
||||
|
||||
/* Struct for controlling attributes which affect enemy spawning base on game difficulty and player count */
|
||||
struct SMonsterSpawnScaling
|
||||
{
|
||||
var () KFStoryGameInfo.SDifficultyWrapper EnemySpawnRate;
|
||||
|
||||
var () KFStoryGameInfo.SDifficultyWrapper NumberOfEnemies;
|
||||
};
|
||||
|
||||
var(Rules_Monsters) SMonsterSpawnScaling Spawn_Difficulty_Scaling;
|
||||
|
||||
/* should bots be allowed to spawn ? */
|
||||
var(Rules_Bots) bool bAllowBots;
|
||||
|
||||
/* Textures to display on the HUD when the match is over */
|
||||
var(Rules_HUD) Material VictoryMaterial,DefeatMaterial;
|
||||
|
||||
/* If a team is restarted after dying during a story mission these are the actor types we need to reset*/
|
||||
var(Rules_CheckPoints) array<class> CheckpointResetClasses ;
|
||||
|
||||
/* If true the weapon / item pickups in the map will be randomly spawned based on difficulty - like in a normal KF match */
|
||||
var(Rules_Equipment) bool bRandomizeWeaponPickups;
|
||||
|
||||
// Amount of starting HP for all players
|
||||
var(Rules_Equipment) int PlayerStartHealth;
|
||||
|
||||
// Amount of starting armor for all players.
|
||||
var(Rules_Equipment) int PlayerStartArmor;
|
||||
|
||||
// Defines starting equipment for players
|
||||
var(Rules_Equipment) array< Class<Inventory> > RequiredPlayerEquipment;
|
||||
|
||||
/* if true, allow high level players to spawn with their 'default' gear */
|
||||
var(Rules_Equipment) bool bAllowPerkStartingWeaps;
|
||||
|
||||
// Enable / Disable Cash display on HUD .
|
||||
var(Rules_HUD) bool bShowCash;
|
||||
|
||||
var(Rules_HUD) name HUDStyle;
|
||||
|
||||
|
||||
function ModifyPlayer( Pawn Other )
|
||||
{
|
||||
if( PlayerStartHealth>0 )
|
||||
Other.Health = PlayerStartHealth;
|
||||
if( PlayerStartArmor>0 )
|
||||
Other.ShieldStrength = PlayerStartArmor;
|
||||
}
|
||||
|
||||
function AddGameInv( Pawn Other )
|
||||
{
|
||||
local int i;
|
||||
local Inventory Inv;
|
||||
|
||||
For( i=0; i<RequiredPlayerEquipment.Length; i++ )
|
||||
{
|
||||
if( RequiredPlayerEquipment[i]==None )
|
||||
Continue;
|
||||
if( Other.FindInventoryType(RequiredPlayerEquipment[i])==None )
|
||||
{
|
||||
Inv = Spawn(RequiredPlayerEquipment[i]);
|
||||
if( Inv != None )
|
||||
{
|
||||
Inv.GiveTo(Other);
|
||||
if ( Inv != None )
|
||||
Inv.PickupFunction(Other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
CashReward_ZEDKills_Modifier=1.000000
|
||||
CashPenalty_Death_Modifier=1.000000
|
||||
bAllowPerkStartingWeaps=True
|
||||
MaxEnemiesAtOnce=32
|
||||
MaxStragglers=5
|
||||
bAutoKillStragglers = true
|
||||
bShowCash = true
|
||||
StartingCashSum = 250
|
||||
|
||||
VictoryMaterial=Combiner'KFMapEndTextures.VictoryCombiner'
|
||||
DefeatMaterial=Combiner'KFMapEndTextures.DefeatCombiner'
|
||||
|
||||
CheckpointResetClasses(0)=Class'ZombieVolume'
|
||||
CheckpointResetClasses(1)=Class'Gameplay.ScriptedSequence'
|
||||
CheckpointResetClasses(2)=Class'Engine.Pickup'
|
||||
CheckpointResetClasses(3)=Class'Engine.Pawn'
|
||||
CheckpointResetClasses(4)=Class'Engine.Triggers'
|
||||
CheckpointResetClasses(5)=Class'Gameplay.TriggerLight'
|
||||
CheckpointResetClasses(6)=Class'Engine.BlockingVolume'
|
||||
CheckPointResetClasses(7)=Class'Engine.Decoration'
|
||||
CheckPointResetClasses(8)=Class'KF_StoryWaveDesigner'
|
||||
CheckPointResetClasses(9)=Class'StaticMeshActor_Hideable'
|
||||
CheckPointResetClasses(10)=Class'KF_StoryWaveDesigner'
|
||||
|
||||
RequiredPlayerEquipment(0)=Class'KFMod.Single'
|
||||
RequiredPlayerEquipment(1)=Class'KFMod.Syringe'
|
||||
RequiredPlayerEquipment(2)=Class'KFMod.Welder'
|
||||
RequiredPlayerEquipment(3)=Class'KFMod.Frag'
|
||||
RequiredPlayerEquipment(4)=Class'KFMod.knife'
|
||||
|
||||
Texture=Texture'KFStoryGame_Tex.Editor.KFRules_Ico'
|
||||
|
||||
bAutoStartObjectives = true
|
||||
bRandomizeWeaponPickups = true
|
||||
|
||||
/* Difficulty Magic Numbers go here! */
|
||||
Spawn_Difficulty_Scaling=(EnemySpawnRate=(Scale_GameDifficulty=(Scale_Beginner=1.0,Scale_Hard=1.17,Scale_Suicidal=1.17,Scale_HellOnEarth=1.17),Scale_PlayerCount=(Scale_1P=1,Scale_2P=1,Scale_3P=1.0,Scale_4P=1.17,Scale_5P=1.53,Scale_6P=3.3)),NumberOfEnemies=(Scale_GameDifficulty=(Scale_Beginner=0.7,Scale_Hard=1.3,Scale_Suicidal=1.5,Scale_HellOnEarth=1.7),Scale_PlayerCount=(Scale_1P=1,Scale_2P=2,Scale_3P=2.75,Scale_4P=3.5,Scale_5P=4,Scale_6P=4.5)))
|
||||
}
|
||||
8
kf_sources/KFStoryGame/Classes/KFOMapList.uc
Normal file
8
kf_sources/KFStoryGame/Classes/KFOMapList.uc
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
class KFOMapList extends MapList
|
||||
config;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Maps(0)="KFO-Steamland"
|
||||
MapNum=1
|
||||
}
|
||||
603
kf_sources/KFStoryGame/Classes/KFPlayerController_Story.uc
Normal file
603
kf_sources/KFStoryGame/Classes/KFPlayerController_Story.uc
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KFPlayerController_Story
|
||||
--------------------------------------------------------------
|
||||
|
||||
Custom PlayerController class for use in Killing Floor 'Story' maps.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KFPlayerController_Story extends KFPlayerController ;
|
||||
|
||||
/* number of times this player has been respawned by the current CheckpointVolume */
|
||||
var int NumCheckPointRespawns;
|
||||
|
||||
/* reference to the last Trader Shop we used */
|
||||
var KFShopVolume_Story CurrentShopVolume;
|
||||
|
||||
var KF_StoryCheckPointVolume CurrentCheckPoint;
|
||||
|
||||
var bool bShowObjectiveDebug;
|
||||
|
||||
/* == Checkpoint Data ===================================================================
|
||||
|
||||
Stuff we want to keep track of when this player is 'checkpointed' during a story mission.
|
||||
|
||||
=========================================================================================
|
||||
*/
|
||||
|
||||
/* array of equipment the pawn was holding when he last activated a checkpoint */
|
||||
var array<String> SavedLoadOut;
|
||||
|
||||
/* the ammo counts for weapons this player had at the time they last activated a checkpoint */
|
||||
var array<Int> SavedAmmo;
|
||||
|
||||
/* the magazine ammo counts for weapons this player had at the time they last activated a checkpoint */
|
||||
var array<Int> SavedMagAmmo;
|
||||
|
||||
/* the cash this player had at the time he last activated a checkpoint */
|
||||
var float SavedCash;
|
||||
|
||||
/* the amount of health this player had at the time he last activated a checkpoint */
|
||||
var int SavedHealth;
|
||||
|
||||
/* the amount of body armor this player had at the time he last activated a checkpoint */
|
||||
var int SavedArmor;
|
||||
|
||||
/* If we are doing a trader time objective this is the number of seconds left before it completes */
|
||||
var float RemainingTraderTime;
|
||||
|
||||
|
||||
replication
|
||||
{
|
||||
unreliable if(Role == Role_Authority)
|
||||
SetClientWhispClr,ClientSetUV2Tex,UnReliableConditionUpdate;
|
||||
|
||||
reliable if(Role == Role_Authority)
|
||||
CurrentShopVolume,ReliableConditionUpdate,ClientShowStoryDialogue, ClientPlayStorySound;
|
||||
|
||||
unreliable if( Role<ROLE_Authority )
|
||||
ServerStopUsing,ServerCompleteObj,ServerFFObj;
|
||||
|
||||
reliable if (Role <ROLE_Authority)
|
||||
ServerReadyLateJoiner;
|
||||
}
|
||||
|
||||
simulated function ClientSetUV2Tex(Actor TargetActor , Material NewUV2Tex)
|
||||
{
|
||||
TargetActor.UV2Texture = NewUV2Tex;
|
||||
}
|
||||
|
||||
simulated function ClientShowStoryDialogue(name DialogueActor, int DlgIndex, float DisplayDuration)
|
||||
{
|
||||
if(HUD_StoryMode(myHUD) != none)
|
||||
{
|
||||
HUD_StoryMode(myHUD).AddDialogue(DialogueActor,DlgIndex,DisplayDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Play a story mode sound on the client
|
||||
// If bAdjustPitch = true then the sound will be adjusted to the game pitch
|
||||
// based on the game speed (i.e. lower pitch if zed time is enabled). If it
|
||||
// is false it will not be adjusted with the game speed
|
||||
simulated function ClientPlayStorySound(sound ASound, float Volume, bool bAdjustPitch )
|
||||
{
|
||||
local float UsedPitch;
|
||||
|
||||
UsedPitch = 1.0;
|
||||
|
||||
if( bAdjustPitch )
|
||||
{
|
||||
UsedPitch = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UsedPitch = 1.1 / Level.TimeDilation;
|
||||
}
|
||||
|
||||
if ( ViewTarget != None )
|
||||
ViewTarget.PlayOwnedSound(ASound,Slot_Interface,Volume,true,,UsedPitch,false);
|
||||
else
|
||||
PlayOwnedSound(ASound,Slot_Interface,Volume,true,, 1.1 / Level.TimeDilation, false);
|
||||
}
|
||||
|
||||
exec simulated function ToggleConditionStack()
|
||||
{
|
||||
if(HUD_StoryMode(myHUD) != none)
|
||||
{
|
||||
HUD_StoryMode(myHUD).bCollapseConditions = !HUD_StoryMode(myHUD).bCollapseConditions;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called on the client - Updates condition data unreliably */
|
||||
simulated function UnreliableConditionUpdate(
|
||||
KF_ObjectiveCondition UpdatedCondition,
|
||||
KF_StoryObjective ObjOwner,
|
||||
float NewProgressPct,
|
||||
Actor NewLocActor,
|
||||
string NewDataString,
|
||||
bool NewComplete)
|
||||
{
|
||||
DoConditionUpdate(UpdatedCondition,ObjOwner.Name,NewProgressPct,NewLocActor,UpdatedCondition.GetHUDHint()@NewDataString,NewComplete, '');
|
||||
}
|
||||
|
||||
/* Called on the client - Updates condition data reliably */
|
||||
simulated function ReliableConditionUpdate(
|
||||
KF_ObjectiveCondition UpdatedCondition,
|
||||
KF_StoryObjective ObjOwner,
|
||||
float NewProgressPct,
|
||||
Actor NewLocActor,
|
||||
string NewDataString,
|
||||
bool NewComplete)
|
||||
{
|
||||
local name PendingLocActorTag;
|
||||
/*
|
||||
log(" *** RELIABLE CONDITION UPDATE ******************************************************");
|
||||
log(" >>> "@UpdatedCondition);
|
||||
log(" *** Progress Percent :"@NewProgressPct);
|
||||
log(" *** Data String :"@NewDataString);
|
||||
log(" *** Complete? :"@NewComplete);
|
||||
*/
|
||||
// If we have an actors tag, but no actor Queue him with PendingLocActorTag to grab his reference later.
|
||||
// This is pretty much a hack to get around cases where we are trying to grab a reference to an actor which
|
||||
// does not yet exist on the client .
|
||||
|
||||
if (NewLocActor == none )
|
||||
{
|
||||
if( UpdatedCondition.IsA('ObjCondition_ActorHealth') )
|
||||
{
|
||||
PendingLocActorTag = ObjCondition_ActorHealth(UpdatedCondition).TargetPawnTag;
|
||||
}
|
||||
else if( UpdatedCondition.IsA('ObjCondition_Use') )
|
||||
{
|
||||
PendingLocActorTag = ObjCondition_Use(UpdatedCondition).UsePawn_Tag;
|
||||
}
|
||||
}
|
||||
|
||||
DoConditionUpdate(UpdatedCondition,ObjOwner.Name,NewProgressPct,NewLocActor,UpdatedCondition.GetHUDHint()@NewDataString,NewComplete,PendingLocActorTag);
|
||||
}
|
||||
|
||||
simulated function DoConditionUpdate(
|
||||
KF_ObjectiveCondition UpdatedCondition,
|
||||
name ObjOwner,
|
||||
float NewProgressPct,
|
||||
Actor NewLocActor,
|
||||
string NewDataString,
|
||||
bool NewComplete,
|
||||
name PendingLocActorTag)
|
||||
{
|
||||
local ObjCondition_Timed TimeCondition;
|
||||
|
||||
if(HUD_StoryMode(myHUD) == none)
|
||||
{
|
||||
log(" WARNING - NO HUD AVAILABLE FOR : "@self@" CLIENT CONDITION UPDATE WILL FAIL. ",'Story_Debug');
|
||||
}
|
||||
|
||||
if(Level.NetMode == NM_DedicatedServer ||
|
||||
HUD_StoryMode(myHUD) == none ||
|
||||
UpdatedCondition == none ||
|
||||
ObjOwner == '')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TimeCondition = ObjCondition_Timed(UpdatedCondition);
|
||||
if(TimeCondition != none &&
|
||||
TimeCondition.bTraderTime)
|
||||
{
|
||||
RemainingTraderTime = TimeCondition.Duration - (TimeCondition.Duration * NewProgressPct);
|
||||
}
|
||||
|
||||
HUD_StoryMode(myHUD).UpdateConditionHint(
|
||||
UpdatedCondition.name,
|
||||
ObjOwner,
|
||||
NewProgressPct,
|
||||
NewLocActor,
|
||||
NewDataString,
|
||||
NewComplete,
|
||||
PendingLocActorTag);
|
||||
}
|
||||
|
||||
|
||||
simulated function SetClientWhispClr(color NewWhispClr)
|
||||
{
|
||||
Class'Objective_Whisp'.default.mColorRange[0] = NewWhispClr;
|
||||
Class'Objective_Whisp'.default.mColorRange[1] = NewWhispClr;
|
||||
}
|
||||
|
||||
|
||||
/* This player's progress was saved at a checkpoint */
|
||||
function SaveLoadOut()
|
||||
{
|
||||
if(PlayerReplicationInfo != none)
|
||||
{
|
||||
SavedCash = PlayerReplicationInfo.Score;
|
||||
}
|
||||
|
||||
if(KFHumanPawn_Story(Pawn) != none)
|
||||
{
|
||||
KFHumanPawn_Story(Pawn).SaveLoadOut() ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Overriden to ensure it opens up the story-friendly version of the Trader Buy Menu */
|
||||
|
||||
function ShowBuyMenu(string wlTag,float maxweight)
|
||||
{
|
||||
StopForceFeedback(); // jdf - no way to pause feedback
|
||||
|
||||
// Open menu
|
||||
ClientOpenMenu("KFStoryUI.GUIBuyMenu_Story",,wlTag,string(maxweight));
|
||||
}
|
||||
|
||||
// Send a voice message of a certain type to a certain player.
|
||||
|
||||
/* Added a hack to filter out trader voices */
|
||||
|
||||
function ServerSpeech( name Type, int Index, string Callsign )
|
||||
{
|
||||
if(Type != 'TRADER')
|
||||
{
|
||||
Super.ServerSpeech(Type,Index,Callsign);
|
||||
}
|
||||
}
|
||||
|
||||
function SetPawnClass(string inClass, string inCharacter)
|
||||
{
|
||||
Super.SetPawnClass(inClass,inCharacter);
|
||||
/* @todo - why doesn't GetDefaultPlayerClass() work ? */
|
||||
// PawnClass = Level.Game.GetDefaultPlayerClass(self); // PawnClass = Class'KFHumanPawn';
|
||||
PawnClass = class 'KFStoryGame.KFHumanPawn_Story';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Helper function for quickly determining whether a player is looking at a point in space.
|
||||
original author : Ron Prestenback.
|
||||
|
||||
* @param TargetLocation the location to check
|
||||
* @param MinDotResult a value between 0 and 1 representing the minimum dot result value that should be
|
||||
* considered acceptable for testing whether the location is within our field of
|
||||
* view. (Default value is corresponds to a maximum angle of around 47 degrees)
|
||||
*
|
||||
* @return TRUE if the location is within the angle specified from the player's line of sight.
|
||||
*/
|
||||
simulated function bool IsLookingAtLocation( vector TargetLocation, optional float MinDotResult)
|
||||
{
|
||||
local vector DirectionNormal, EyesLoc;
|
||||
local rotator EyesRot;
|
||||
local float ViewAngleCosine;
|
||||
|
||||
// get the location and rotation of the camera
|
||||
EyesLoc = CalcViewLocation;;
|
||||
EyesRot = CalcViewRotation;
|
||||
|
||||
// get the normalized distance between the two locations
|
||||
DirectionNormal = Normal(TargetLocation - EyesLoc);
|
||||
|
||||
// get the dot result of the player's view location and the target location
|
||||
ViewAngleCosine = DirectionNormal dot vector(EyesRot);
|
||||
|
||||
// determine if the angle between our camera's rotation and the target location is within range.
|
||||
// log("IS LOOKING AT LOCATION - "@ViewAngleCosine@" Required : "@MinDotResult);
|
||||
return ViewAngleCosine >= MinDotResult;
|
||||
}
|
||||
|
||||
|
||||
simulated function bool HasLineOfSightTo( vector TargetLocation)
|
||||
{
|
||||
return IsLookingAtLocation(TargetLocation,0.5f) && FastTrace(CalcViewLocation, TargetLocation) && FastTrace(TargetLocation,CalcViewLocation); //EyePostion() is returning a funny value sometimes. Not sure why. C.Pawn./*EyePosition()*/Location
|
||||
}
|
||||
|
||||
/* Extended 'Use' functionality - Support for OnRelease events */
|
||||
|
||||
// The player wants to stop using something in the level.
|
||||
exec function StopUsing()
|
||||
{
|
||||
ServerStopUsing();
|
||||
// log(self@"stopped pressing Use");
|
||||
}
|
||||
|
||||
|
||||
/* === Server Debug Commands ==================
|
||||
===============================================*/
|
||||
|
||||
/* Fast Forward*/
|
||||
exec function FFObj(name ObjName)
|
||||
{
|
||||
if( !class'ROEngine.ROLevelInfo'.static.RODebugMode() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ServerFFObj(ObjName);
|
||||
}
|
||||
|
||||
/* Helpful function for level Designers testing objectives at different stages in their map
|
||||
|
||||
Changes the active objective to the one provided. If bSimulateCompletion, it will also fast forward
|
||||
through the Objective chain in an attempt to simulate actual player progression. */
|
||||
|
||||
function ServerFFObj(name ObjName)
|
||||
{
|
||||
local KF_StoryObjective NewObj;
|
||||
local KFStoryGameInfo StoryGI;
|
||||
|
||||
StoryGI = KFStoryGameInfo(Level.Game);
|
||||
if(StoryGI == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NewObj = StoryGI.FindObjectiveNamed(ObjName);
|
||||
if(NewObj != none && !StoryGI.bGameEnded )
|
||||
{
|
||||
if(!NewObj.IsValidForActivation())
|
||||
{
|
||||
ClientMessage("WARNING : ["@NewObj.ObjectiveName@"] has already been completed and is a non-recurring objective. It cannot be activated");
|
||||
return ;
|
||||
}
|
||||
|
||||
if(NewObj != StoryGI.CurrentObjective)
|
||||
{
|
||||
StoryGI.ForcedTargetObj = NewObj;
|
||||
StoryGI.bSkipDialogue = true;
|
||||
|
||||
if(KF_StoryGRI(StoryGI.GameReplicationInfo) != none)
|
||||
{
|
||||
KF_StoryGRI(StoryGI.GameReplicationInfo).SetDebugTargetObj(NewObj);
|
||||
}
|
||||
|
||||
StoryGI.GoToForcedObj();
|
||||
ClientMessage("Fast tracking to ... "@NewObj.ObjectiveName,'CriticalEventPlus');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientMessage("WARNING : cannot find objective : "@ObjName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
exec function CompleteObj()
|
||||
{
|
||||
if( !class'ROEngine.ROLevelInfo'.static.RODebugMode() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ServerCompleteObj();
|
||||
}
|
||||
|
||||
function ServerCompleteObj()
|
||||
{
|
||||
local KF_StoryObjective CurrentObjective;
|
||||
|
||||
if(KFStoryGameInfo(Level.Game) != none )
|
||||
{
|
||||
CurrentObjective = KFStoryGameInfo(Level.Game).CurrentObjective ;
|
||||
if(CurrentObjective != none)
|
||||
{
|
||||
if(CurrentObjective.bCompleted)
|
||||
{
|
||||
Level.GetLocalPlayerController().ClientMessage("WARNING : ["@CurrentObjective.ObjectiveName@"] is already COMPLETE. ",'Story_Debug');
|
||||
return ;
|
||||
}
|
||||
|
||||
CurrentObjective.ForceCompleteObjective();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exec function StartUsing()
|
||||
{
|
||||
Super.ServerUse();
|
||||
}
|
||||
|
||||
function ServerUse()
|
||||
{
|
||||
Super.ServerUse();
|
||||
|
||||
/* Hackey hack time!*/
|
||||
if(KFStoryGameInfo(Level.Game) != none &&
|
||||
KFStoryGameInfo(Level.Game).CurrentObjective != none)
|
||||
{
|
||||
KFStoryGameInfo(Level.Game).CurrentObjective.UsedBy(pawn);
|
||||
}
|
||||
}
|
||||
|
||||
function ServerStopUsing()
|
||||
{
|
||||
if ( Role < ROLE_Authority )
|
||||
return;
|
||||
|
||||
if ( Level.Pauser == PlayerReplicationInfo )
|
||||
{
|
||||
SetPause(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Pawn == None || !Pawn.bCanUse)
|
||||
return;
|
||||
|
||||
/* Hackey hack time!*/
|
||||
if(KFStoryGameInfo(Level.Game) != none &&
|
||||
KFStoryGameInfo(Level.Game).CurrentObjective != none)
|
||||
{
|
||||
KFStoryGameInfo(Level.Game).CurrentObjective.StoppedUsing(pawn);
|
||||
}
|
||||
}
|
||||
|
||||
exec function SoakAI()
|
||||
{
|
||||
local AIController Bot;
|
||||
|
||||
log("Start Soaking");
|
||||
UnrealMPGameInfo(Level.Game).bSoaking = true;
|
||||
ForEach DynamicActors(class'AIController',Bot)
|
||||
Bot.bSoaking = true;
|
||||
}
|
||||
|
||||
exec function ObjDebug()
|
||||
{
|
||||
bShowObjectiveDebug = !bShowObjectiveDebug;
|
||||
}
|
||||
|
||||
simulated function DisplayDebug(Canvas Canvas, out float YL, out float YPos)
|
||||
{
|
||||
local KFStoryGameInfo StoryGI;
|
||||
local int i;
|
||||
|
||||
StoryGI = KFStoryGameInfo(Level.Game);
|
||||
if (StoryGI != none && bShowObjectiveDebug)
|
||||
{
|
||||
Canvas.SetDrawColor(50, 255, 50);
|
||||
Canvas.DrawText("========== OBJECTIVE LIST ======================");
|
||||
|
||||
for(i = 0 ; i < StoryGI.AllObjectives.length ; i ++)
|
||||
{
|
||||
Canvas.DrawText("["$i+1$"]"@StoryGI.AllObjectives[i].ObjectiveName);
|
||||
}
|
||||
|
||||
YPos += YL/2;
|
||||
Canvas.SetPos(4, YPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
Super.DisplayDebug(Canvas, YL, YPos);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function UpdateHintManagement(bool bUseHints)
|
||||
{
|
||||
if (Level.GetLocalPlayerController() == self)
|
||||
{
|
||||
if (bUseHints && HintManager == none)
|
||||
{
|
||||
HintManager = spawn(class'KFHintManager_Story', self);
|
||||
if (HintManager == none)
|
||||
warn("Unable to spawn hint manager");
|
||||
}
|
||||
else if (!bUseHints && HintManager != none)
|
||||
{
|
||||
HintManager.Destroy();
|
||||
HintManager = none;
|
||||
}
|
||||
|
||||
if (!bUseHints)
|
||||
if (HUDKillingFloor(myHUD) != none)
|
||||
HUDKillingFloor(myHUD).bDrawHint = false;
|
||||
}
|
||||
}
|
||||
|
||||
function ServerThrowWeapon()
|
||||
{
|
||||
// If we have any story items, throw them one at a time
|
||||
if( KFHumanPawn_Story(Pawn) != none &&
|
||||
KFHumanPawn_Story(Pawn).IsCarryingThrowableInventory())
|
||||
{
|
||||
KFHumanPawn_Story(Pawn).TossSingleCarriedItem();
|
||||
}
|
||||
else
|
||||
{
|
||||
super.ServerThrowWeapon();
|
||||
}
|
||||
}
|
||||
|
||||
/* A late joining client wants to tell the server he's ready to play .. */
|
||||
function ServerReadyLateJoiner()
|
||||
{
|
||||
if ( !Level.Game.bWaitingToStartMatch )
|
||||
PlayerReplicationInfo.bReadyToPlay = true;
|
||||
}
|
||||
|
||||
function SelectVeterancy(class<KFVeterancyTypes> VetSkill, optional bool bForceChange)
|
||||
{
|
||||
if ( VetSkill == none || KFPlayerReplicationInfo(PlayerReplicationInfo) == none )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( KFSteamStatsAndAchievements(SteamStatsAndAchievements) != none )
|
||||
{
|
||||
SetSelectedVeterancy( VetSkill );
|
||||
|
||||
if ( KFStoryGameInfo(Level.Game) != none && // another place where we gotta use IsTraderObj() instead of bWaveInProgress ...
|
||||
!KFStoryGameInfo(Level.Game).IsTraderTime() &&
|
||||
VetSkill != KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill )
|
||||
{
|
||||
bChangedVeterancyThisWave = false;
|
||||
ClientMessage(Repl(YouWillBecomePerkString, "%Perk%", VetSkill.Default.VeterancyName));
|
||||
}
|
||||
else if ( !bChangedVeterancyThisWave || bForceChange )
|
||||
{
|
||||
if ( VetSkill != KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill )
|
||||
{
|
||||
ClientMessage(Repl(YouAreNowPerkString, "%Perk%", VetSkill.Default.VeterancyName));
|
||||
}
|
||||
|
||||
if ( GameReplicationInfo.bMatchHasBegun )
|
||||
{
|
||||
bChangedVeterancyThisWave = true;
|
||||
}
|
||||
|
||||
KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill = VetSkill;
|
||||
KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkillLevel = KFSteamStatsAndAchievements(SteamStatsAndAchievements).PerkHighestLevelAvailable(VetSkill.default.PerkIndex);
|
||||
|
||||
if( KFHumanPawn(Pawn) != none )
|
||||
{
|
||||
KFHumanPawn(Pawn).VeterancyChanged();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientMessage(PerkChangeOncePerWaveString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
state Dead
|
||||
{ /*
|
||||
function Timer()
|
||||
{
|
||||
There was some forced respawn code in KFGameType's implementation ...
|
||||
I'm trying to cut out anything that could interfere with
|
||||
the Story game's checkpoint respawn system
|
||||
|
||||
super(PlayerController).Timer();
|
||||
} */
|
||||
|
||||
function Timer()
|
||||
{
|
||||
/* I REALLY hate to do this, but it's the only way to get it to work like it does in KFGameType*/
|
||||
if ( KFGameType(Level.Game) != none && Level.Game.GameReplicationInfo.bMatchHasBegun &&
|
||||
Role == ROLE_Authority && KFStoryGameInfo(Level.Game).IsTraderTime() )
|
||||
{
|
||||
PlayerReplicationInfo.Score = Max(KFGameType(Level.Game).MinRespawnCash, int(PlayerReplicationInfo.Score));
|
||||
SetViewTarget(self);
|
||||
ClientSetBehindView(false);
|
||||
bBehindView = False;
|
||||
ClientSetViewTarget(Pawn);
|
||||
PlayerReplicationInfo.bOutOfLives = false;
|
||||
Pawn = none;
|
||||
ServerReStartPlayer();
|
||||
}
|
||||
|
||||
super.Timer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
PlayerReplicationInfoClass=class'KFStoryGame.KF_StoryPRI'
|
||||
// bWantsTraderPath = true
|
||||
LobbyMenuClassString="KFStoryUI.LobbyMenu_Story"
|
||||
}
|
||||
|
||||
|
||||
82
kf_sources/KFStoryGame/Classes/KFScoreBoard_Story.uc
Normal file
82
kf_sources/KFStoryGame/Classes/KFScoreBoard_Story.uc
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KFScoreBoard_Story
|
||||
--------------------------------------------------------------
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KFScoreBoard_Story extends KFScoreboardNew;
|
||||
|
||||
/* Override to replace the Wavestring with the Title of the current objective */
|
||||
|
||||
function DrawTitle(Canvas Canvas, float HeaderOffsetY, float PlayerAreaY, float PlayerBoxSizeY)
|
||||
{
|
||||
local string TitleString, ScoreInfoString, RestartString;
|
||||
local float TitleXL, ScoreInfoXL, YL, TitleY, TitleYL;
|
||||
local KF_StoryObjective CurrentObj;
|
||||
local string ObjString;
|
||||
|
||||
if(KF_StoryGRI(GRI) != none)
|
||||
{
|
||||
CurrentObj = KF_StoryGRI(GRI).GetCurrentObjective() ;
|
||||
if(CurrentObj != none)
|
||||
{
|
||||
ObjString = CurrentObj.HUD_Header.Header_Text ;
|
||||
}
|
||||
}
|
||||
|
||||
TitleString = SkillLevel[Clamp(InvasionGameReplicationInfo(GRI).BaseDifficulty, 0, 7)] @ "|" @ ObjString @ "|" @ Level.Title;
|
||||
|
||||
Canvas.Font = class'ROHud'.static.GetSmallMenuFont(Canvas);
|
||||
|
||||
Canvas.StrLen(TitleString, TitleXL, TitleYL);
|
||||
|
||||
if ( GRI.TimeLimit != 0 )
|
||||
{
|
||||
ScoreInfoString = TimeLimit $ FormatTime(GRI.RemainingTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScoreInfoString = FooterText @ FormatTime(GRI.ElapsedTime);
|
||||
}
|
||||
|
||||
Canvas.DrawColor = HUDClass.default.RedColor;
|
||||
|
||||
if ( UnrealPlayer(Owner).bDisplayLoser )
|
||||
{
|
||||
ScoreInfoString = class'HUDBase'.default.YouveLostTheMatch;
|
||||
}
|
||||
else if ( UnrealPlayer(Owner).bDisplayWinner )
|
||||
{
|
||||
ScoreInfoString = class'HUDBase'.default.YouveWonTheMatch;
|
||||
}
|
||||
else if ( PlayerController(Owner).IsDead() )
|
||||
{
|
||||
RestartString = Restart;
|
||||
|
||||
if ( PlayerController(Owner).PlayerReplicationInfo.bOutOfLives )
|
||||
{
|
||||
RestartString = OutFireText;
|
||||
}
|
||||
|
||||
ScoreInfoString = RestartString;
|
||||
}
|
||||
|
||||
TitleY = Canvas.ClipY * 0.13;
|
||||
Canvas.SetPos(0.5 * (Canvas.ClipX - TitleXL), TitleY);
|
||||
Canvas.DrawText(TitleString);
|
||||
|
||||
Canvas.StrLen(ScoreInfoString, ScoreInfoXL, YL);
|
||||
Canvas.SetPos(0.5 * (Canvas.ClipX - ScoreInfoXL), TitleY + TitleYL);
|
||||
Canvas.DrawText(ScoreInfoString);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
76
kf_sources/KFStoryGame/Classes/KFShopVolume_Story.uc
Normal file
76
kf_sources/KFStoryGame/Classes/KFShopVolume_Story.uc
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KeyPickup_Story
|
||||
--------------------------------------------------------------
|
||||
|
||||
Custom ShopVolume for use in Story missions.
|
||||
|
||||
Implements its own version of the LevelRules actor's 'ItemForSale'
|
||||
functionality, so that different story shops can be configured with
|
||||
their own unique item lists.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KFShopVolume_Story extends ShopVolume;
|
||||
|
||||
/* stuff this shop sells */
|
||||
var () array<class<Pickup> > SaleItems;
|
||||
|
||||
/* Text to display to players when they open the shop menu */
|
||||
var () string WelcomeText;
|
||||
|
||||
/* Title of shop - displayed in the UI's header */
|
||||
var() string ShopName;
|
||||
|
||||
/* Toggles display of the 'perks' header in the trader UI */
|
||||
var() bool bShowPerkHeader;
|
||||
|
||||
|
||||
|
||||
/* fix for accessed nones */
|
||||
function Touch( Actor Other )
|
||||
{
|
||||
if(MyTrader != none)
|
||||
{
|
||||
Super.Touch(Other);
|
||||
}
|
||||
}
|
||||
|
||||
/* fix for accessed nones */
|
||||
function UnTouch( Actor Other )
|
||||
{
|
||||
if(MyTrader != none)
|
||||
{
|
||||
Super.UnTouch(Other);
|
||||
}
|
||||
}
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
SetCollision(!bCollideActors);
|
||||
}
|
||||
|
||||
|
||||
function UsedBy( Pawn user )
|
||||
{
|
||||
local KFPlayerController_Story StoryUser;
|
||||
|
||||
/* Grab a reference to this shop volume - we'll use it in the Trader UI Pages */
|
||||
StoryUser = KFPlayerController_Story(user.Controller);
|
||||
if(StoryUser != none)
|
||||
{
|
||||
StoryUser.CurrentShopVolume = self;
|
||||
}
|
||||
|
||||
Super.UsedBy(User);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bShowPerkHeader = true
|
||||
bStatic = false
|
||||
}
|
||||
|
||||
2241
kf_sources/KFStoryGame/Classes/KFStoryGameInfo.uc
Normal file
2241
kf_sources/KFStoryGame/Classes/KFStoryGameInfo.uc
Normal file
File diff suppressed because it is too large
Load diff
11
kf_sources/KFStoryGame/Classes/KFStoryRoster.uc
Normal file
11
kf_sources/KFStoryGame/Classes/KFStoryRoster.uc
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
class KFStoryRoster extends xTeamRoster;
|
||||
|
||||
function bool AddToTeam( Controller Other )
|
||||
{
|
||||
if(Other.PlayerReplicationinfo == none)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Super.AddToTeam(Other);
|
||||
}
|
||||
19
kf_sources/KFStoryGame/Classes/KFTeamAI_Story.uc
Normal file
19
kf_sources/KFStoryGame/Classes/KFTeamAI_Story.uc
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
//-----------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
class KFTeamAI_Story extends KFTeamAI;
|
||||
|
||||
/* Hack for story NPCs - check their team Index number instead of the TeamInfo object ..
|
||||
(They dont actually get put on teams with human players) */
|
||||
|
||||
function bool FriendlyToward(Pawn Other)
|
||||
{
|
||||
if(KF_StoryNPC(Other) != none)
|
||||
{
|
||||
return KF_StoryNPC(Other).TeamIndex == Team.TeamIndex ;
|
||||
}
|
||||
|
||||
return Super.OnThisTeam(Other);
|
||||
}
|
||||
|
||||
|
||||
105
kf_sources/KFStoryGame/Classes/KFUseTrigger_Story.uc
Normal file
105
kf_sources/KFStoryGame/Classes/KFUseTrigger_Story.uc
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KFUseTrigger_Story
|
||||
--------------------------------------------------------------
|
||||
|
||||
Custom Use Trigger that can trigger additional events.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class KFUseTrigger_Story extends KFUseTrigger;
|
||||
|
||||
/* event to fire off when the doors associated with this trigger have been fully welded shut */
|
||||
var(Events) name FullWeldEvent;
|
||||
|
||||
/* if true, this trigger starts life dormant. it can only be 'used' once it has been triggered */
|
||||
var() bool bTriggerEnabled;
|
||||
|
||||
var() bool bEnabled;
|
||||
|
||||
var() bool bAllowZEDInteraction;
|
||||
|
||||
var() bool bShouldBeEnabledInWaveMode;
|
||||
|
||||
function PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
if(KFStoryGameinfo(Level.Game) == none)
|
||||
{
|
||||
bEnabled = bShouldBeEnabledInWaveMode;
|
||||
}
|
||||
}
|
||||
|
||||
function bool TriggerIsUseable()
|
||||
{
|
||||
return bEnabled && bCollideActors;
|
||||
}
|
||||
|
||||
function AddWeld( float ExtraWeld, bool bZombieAttacking, Pawn WelderInst )
|
||||
{
|
||||
if(!TriggerIsUseable() && WelderInst != none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Super.AddWeld(ExtraWeld,bZombieAttacking,WelderInst);
|
||||
|
||||
if(WeldStrength >= MaxWeldStrength)
|
||||
{
|
||||
TriggerEvent(FullWeldEvent,self,none);
|
||||
}
|
||||
}
|
||||
|
||||
function UnWeld(float DeWeldage,bool bZombieAttacking, Pawn WelderInst)
|
||||
{
|
||||
if(!TriggerIsUseable() && WelderInst != none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Super.UnWeld(DeWeldage,bZombieAttacking,WelderInst);
|
||||
}
|
||||
|
||||
function UsedBy(Pawn user)
|
||||
{
|
||||
if(!TriggerIsUseable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Super.UsedBy(user);
|
||||
}
|
||||
|
||||
function Touch( Actor Other )
|
||||
{
|
||||
if(bEnabled && (!Other.IsA('KFMonster') || bAllowZEDInteraction))
|
||||
{
|
||||
Super.Touch(Other);
|
||||
}
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
bEnabled = !bTriggerEnabled ;
|
||||
}
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
if(bTriggerEnabled)
|
||||
{
|
||||
bEnabled = !bEnabled;
|
||||
}
|
||||
|
||||
Super.Trigger(other,EventInstigator);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bShouldBeEnabledInWaveMode = true
|
||||
bEnabled = true
|
||||
}
|
||||
253
kf_sources/KFStoryGame/Classes/KF_BreakerBoxNPC.uc
Normal file
253
kf_sources/KFStoryGame/Classes/KF_BreakerBoxNPC.uc
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryNPC_Static
|
||||
--------------------------------------------------------------
|
||||
|
||||
Repairable breaker box NPC for use in Objective missions.
|
||||
Has support for different visual damage states.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class KF_BreakerBoxNPC extends KF_StoryNPC_Static;
|
||||
|
||||
var float LastTriggerEventTime;
|
||||
|
||||
var Material BrokenMat,FixedMat;
|
||||
|
||||
var () bool bWeldable;
|
||||
|
||||
var(Events) name Event_FullHealth,Event_NoHealth;
|
||||
|
||||
var bool bRepaired,SavedbFullhealth,bDestroyed,SavedbNoHealth;
|
||||
|
||||
var(Display) StaticMesh HealthyMesh,DestroyedMesh;
|
||||
|
||||
var class<Emitter> HitEmitter;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if(Role == Role_Authority && bNetDirty)
|
||||
bRepaired;
|
||||
}
|
||||
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
if(bCheckPointed)
|
||||
{
|
||||
bRepaired = SavedbFullHealth;
|
||||
bDestroyed = SavedbNoHealth;
|
||||
}
|
||||
|
||||
CheckHealthCondition(self);
|
||||
}
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
Super.PostbeginPlay();
|
||||
|
||||
CheckHealthCondition(self);
|
||||
bHidden = true; // breaker boxes start out hidden and non-interactable.
|
||||
SetCollision(false,false);
|
||||
}
|
||||
|
||||
function SetActive(bool On)
|
||||
{
|
||||
Super.SetActive(On);
|
||||
|
||||
if(bActive)
|
||||
{
|
||||
bHidden = false;
|
||||
SetCollision(true,true);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Tick(float DeltaTime)
|
||||
{
|
||||
Super.Tick(DeltaTime);
|
||||
|
||||
if(!bDestroyed && Level.TimeSeconds -LastTriggerEventTime > 1.0)
|
||||
{
|
||||
LastTriggerEventTime = Level.TimeSeconds;
|
||||
TriggerEvent('IncrementPower',self,self);
|
||||
}
|
||||
}
|
||||
|
||||
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
local bool bHealed;
|
||||
|
||||
if ( bWeldable && damageType == class 'DamTypeWelder' )
|
||||
{
|
||||
Health = Min(Health + Damage, NPCHealth);
|
||||
bHealed = true;
|
||||
}
|
||||
|
||||
CheckHealthCondition(InstigatedBy);
|
||||
|
||||
if(bHealed)
|
||||
{
|
||||
return; // can skip the rest of the takedamage stuff.
|
||||
}
|
||||
|
||||
Super.TakeDamage(Damage,InstigatedBy,HitLocation,Momentum,damageType,HitIndex);
|
||||
|
||||
CheckhealthCondition(InstigatedBy);
|
||||
}
|
||||
|
||||
|
||||
simulated function CheckHealthCondition(Pawn InstigatedBy)
|
||||
{
|
||||
if(!bRepaired && Health >= NPCHealth)
|
||||
{
|
||||
bRepaired = true;
|
||||
bDestroyed = false;
|
||||
|
||||
TriggerEvent(Event_FullHealth,self,InstigatedBy);
|
||||
|
||||
if(HealthyMesh != none)
|
||||
{
|
||||
SetStaticMesh(HealthyMesh);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!bDestroyed && Health <= 0 )
|
||||
{
|
||||
bDestroyed = true;
|
||||
bRepaired = false;
|
||||
|
||||
TriggerEvent(Event_NoHealth,self,InstigatedBy);
|
||||
|
||||
if(DestroyedMesh != none)
|
||||
{
|
||||
SetStaticMesh(DestroyedMesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw additional icons for Breaker boxes */
|
||||
|
||||
simulated event PostRender2D(Canvas C, float ScreenLocX, float ScreenLocY) // called if bScriptPostRender is true, overrides native team beacon drawing code
|
||||
{
|
||||
local PlayerController PC;
|
||||
local float Opacity;
|
||||
// local float Dist;
|
||||
local HUDKillingFloor KFHUD;
|
||||
local float IconSize;
|
||||
local float XCentre,YCentre;
|
||||
local vector ScreenPos;
|
||||
local float HealthPct;
|
||||
local Material RenderMat;
|
||||
local vector CameraLocation,CamDir;
|
||||
local rotator CameraRotation;
|
||||
|
||||
if(!bShowHealthBar ||
|
||||
!bActive ||
|
||||
GetStateName() == 'Dying' )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IconSize = 64.f * (C.SizeX/1920.f);
|
||||
|
||||
PC = Level.GetLocalPlayerController();
|
||||
if ( PC != None )
|
||||
{
|
||||
KFHUD = HUDKillingFloor(PC.myHUD);
|
||||
if(KFHUD != none)
|
||||
{
|
||||
C.GetCameraLocation(CameraLocation, CameraRotation);
|
||||
CamDir = vector(CameraRotation);
|
||||
|
||||
/* Dont render stuff behind the camera */
|
||||
if ( (Normal(Location - CameraLocation) dot vector(CameraRotation)) < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(bRepaired)
|
||||
{
|
||||
RenderMat = FixedMat ;
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderMat = BrokenMat;
|
||||
}
|
||||
|
||||
ScreenPos = C.WorldToScreen(Location);
|
||||
XCentre = ScreenPos.X;
|
||||
YCentre = ScreenPos.Y;
|
||||
|
||||
Opacity = FClamp(1.f - (VSize(PC.CalcViewLocation - Location) / 3000.f),0.4f,1.f) ;
|
||||
HealthPct = FClamp(float(Health) / NPCHealth,0.f,1.f);
|
||||
|
||||
C.DrawColor.R = Lerp(HealthPct,255,0);
|
||||
C.DrawColor.G = Lerp(HealthPct,0,255);
|
||||
C.DrawColor.B = 50;
|
||||
C.DrawColor.A = Opacity * 255;
|
||||
|
||||
C.SetPos(XCentre - (0.5 * IconSize) + 1.0, YCentre - (0.5 * IconSize) + 1.0);
|
||||
C.DrawTileScaled(RenderMat, IconSize/ RenderMat.MaterialVSize() ,IconSize/ RenderMat.MaterialVSize() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Breaker boxes should never spawn gibs even if it looks cool
|
||||
simulated function SpawnGibs(Rotator HitRotation, float ChunkPerterbation)
|
||||
{}
|
||||
|
||||
// Replace the damage type hit emitter with a custom one
|
||||
function SpawnHitEmitter( float Damage, Pawn InstigatedBy, vector HitLocation, class<DamageType> damageType, vector Momentum )
|
||||
{
|
||||
local Vector HitNormal;
|
||||
|
||||
// Play any set effect
|
||||
if ( EffectIsRelevant(Location,true) )
|
||||
{
|
||||
if (HitEmitter != None)
|
||||
{
|
||||
if( InstigatedBy != none )
|
||||
HitNormal = Normal((InstigatedBy.Location+(vect(0,0,1)*InstigatedBy.EyeHeight))-HitLocation);
|
||||
|
||||
Spawn(HitEmitter,,,HitLocation+HitNormal + (-HitNormal * CollisionRadius), Rotator(HitNormal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
NotThreateningTo(0)= class 'ZombieFleshPound'
|
||||
NotThreateningTo(1)= class 'ZombieScrake'
|
||||
|
||||
DrawScale = 0.5
|
||||
Skins(0) = none
|
||||
|
||||
FixedMat = Texture 'KFStoryGame_Tex.HUD.Electricity_Icon_64'
|
||||
BrokenMat = Texture 'KFStoryGame_Tex.HUD.Repair_Icon_64_BW'
|
||||
StaticMesh = StaticMesh'Props_ObjectiveMode.Breaker_Box'
|
||||
DestroyedMesh = StaticMesh 'Props_ObjectiveMode.Breaker_Box_DMG'
|
||||
HealthyMesh = StaticMesh'Props_ObjectiveMode.Breaker_Box'
|
||||
|
||||
BaseAIThreatRating = 0.010000
|
||||
FriendlyFireDamageScale = 0
|
||||
NPCHealth = 200.000000
|
||||
NPCName = "Breaker Box"
|
||||
StartingHealthPct = 0
|
||||
bStartActive = false
|
||||
bShowHealthBar = true
|
||||
bIndestructible = true
|
||||
bWeldable = true
|
||||
|
||||
HitEmitter=class 'kfmod.Breaker_Damaged_OneOff'
|
||||
ProjectileBloodSplatClass=none
|
||||
|
||||
CollisionRadius=30
|
||||
PrePivot=(X=0,Y=0,Z=30)
|
||||
}
|
||||
464
kf_sources/KFStoryGame/Classes/KF_DialogueSpot.uc
Normal file
464
kf_sources/KFStoryGame/Classes/KF_DialogueSpot.uc
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_DialogueSpot
|
||||
--------------------------------------------------------------
|
||||
|
||||
Displays dialogue on the screen with a header and image.
|
||||
Optionally plays voicover audio.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class KF_DialogueSpot extends Info
|
||||
dependson(KFStoryGameInfo)
|
||||
placeable;
|
||||
|
||||
var int CurrentMsgIdx;
|
||||
|
||||
var Controller DialogueInstigator;
|
||||
|
||||
var() array<KFStoryGameInfo.SDialogueEntry> Dialogues;
|
||||
|
||||
/* true if this dialogue spot should display its text when a player touches the dialogue actor's collision cylinder */
|
||||
var bool bTouchTriggered;
|
||||
|
||||
|
||||
/* true if this dialogue can be 'skipped' by moving out of range of the speaker*/
|
||||
var bool bCanSkipDlg;
|
||||
|
||||
/* the range at which dialogue will be skipped if bCanSkipDlg*/
|
||||
var float SkipDlgRange;
|
||||
|
||||
/* if true, the dialogue will play randomly each time it is triggered rather than in order */
|
||||
var() bool bRandomize;
|
||||
|
||||
// if true, this dialogue can be played multiple times. If not, only allow one play of each dialogue
|
||||
var() bool bAllowRepeatDialogue;
|
||||
|
||||
var bool bDebugDialogue;
|
||||
|
||||
var bool bTraversing;
|
||||
|
||||
var bool bFinished;
|
||||
|
||||
var bool bSingleTouchOnly;
|
||||
|
||||
var bool bTouched;
|
||||
|
||||
|
||||
function Reset()
|
||||
{
|
||||
local int i, SavedIdx;
|
||||
local array<byte> SavedTriggerStates;
|
||||
|
||||
Super.Reset();
|
||||
|
||||
/* Partial reset using saved positions*/
|
||||
|
||||
bTraversing = false;
|
||||
|
||||
if(!bFinished)
|
||||
{
|
||||
SavedIdx = KFStoryGameInfo(Level.Game).CurrentCheckPoint.GetSavedDialogueIndexFor(self,SavedTriggerStates) ;
|
||||
CurrentMsgIdx = SavedIdx;
|
||||
|
||||
if(bDebugDialogue)
|
||||
{
|
||||
log("----- DIALOGUE DEBUG ------ Resetting "@self@". Dialogue will play back from Index : "@SavedIdx, 'Story_Debug');
|
||||
}
|
||||
|
||||
for(i = 0 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
Dialogues[i].bWasTriggered = bool(SavedTriggerStates[i]);
|
||||
}
|
||||
}
|
||||
else /* Full reset from the start. */
|
||||
{
|
||||
for(i = 0 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
Dialogues[i].bWasTriggered = false;
|
||||
}
|
||||
|
||||
CurrentMsgIdx = 0;
|
||||
bFinished = false;
|
||||
}
|
||||
}
|
||||
|
||||
function Destroyed()
|
||||
{
|
||||
local int i;
|
||||
|
||||
/* Perform cleanup on any event listeners */
|
||||
for(i = 0 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
if(Dialogues[i].EventListener != none)
|
||||
{
|
||||
Dialogues[i].EventListener.Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Dialogue callback - timing is handled in the event listener */
|
||||
function OnDialogueDisplayComplete(int Index)
|
||||
{
|
||||
// log("Dialogue - Triggering Displayed Event : "@Dialogues[Index].Events.DisplayedEvent);
|
||||
if(Dialogues[Index].Events.DisplayedEvent != '')
|
||||
{
|
||||
TriggerEvent(Dialogues[Index].Events.DisplayedEvent,self,DialogueInstigator.Pawn);
|
||||
}
|
||||
|
||||
Dialogues[Index].bWasTriggered = false;
|
||||
}
|
||||
|
||||
function PostBeginPlay()
|
||||
{
|
||||
local int i;
|
||||
local Dialogue_EventListener NewListener;
|
||||
|
||||
/* No KFO Gametype, no Initialization */
|
||||
if(KFStoryGameinfo(Level.Game) == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawn Event listeners for Dialogue entries which require them.
|
||||
for(i = 0 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
NewListener = Spawn(class 'Dialogue_EventListener',self,Dialogues[i].Events.RequiredEvent);
|
||||
NewListener.AssociatedIndex = i ;
|
||||
Dialogues[i].EventListener = NewListener;
|
||||
}
|
||||
}
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
if(EventInstigator != none &&
|
||||
EventInstigator.Controller != none)
|
||||
{
|
||||
DialogueInstigator = EventInstigator.Controller;
|
||||
}
|
||||
|
||||
TraverseDialogue();
|
||||
}
|
||||
|
||||
function bool SelfTriggered()
|
||||
{
|
||||
return bTouchTriggered;
|
||||
}
|
||||
|
||||
function Touch( Actor Other )
|
||||
{
|
||||
if ( Pawn(Other) != None &&
|
||||
PlayerController(Pawn(Other).Controller) != none &&
|
||||
SelfTriggered() &&
|
||||
(!bSingleTouchOnly || !bTouched))
|
||||
{
|
||||
bTouched = true;
|
||||
Trigger(self,Pawn(Other));
|
||||
}
|
||||
}
|
||||
|
||||
function int GetIndexFor(KFstoryGameInfo.SDialogueEntry TestDlg)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for(i = 0 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
if(Dialogues[i] == TestDlg)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return - 1 ;
|
||||
}
|
||||
|
||||
|
||||
/* Retrieves the index of the next dialogue entry in a DialogueSpot actor with a 'required event'.
|
||||
Necessary in cases where the game is restarting from an objective in a non-linear fashion and
|
||||
certain intermediate dialogue needs to be skipped
|
||||
*/
|
||||
|
||||
function int GetNextDlgRequiredEventIdx(int TestIndex)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for( i = TestIndex + 1 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
if(Dialogues[i].Events.RequiredEvent != '')
|
||||
{
|
||||
return i ;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
function TraverseDialogue()
|
||||
{
|
||||
local bool bWaitingForEvent ;
|
||||
|
||||
/* Hit the end. early out */
|
||||
if( Dialogues.length <= CurrentMsgIdx || bTraversing || (bFinished && !bAllowRepeatDialogue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(bRandomize)
|
||||
{
|
||||
CurrentMsgIdx = RandRange(0,Dialogues.length) ;
|
||||
}
|
||||
|
||||
/* If the next index after this one is event-triggered, don't set the timer */
|
||||
if(Dialogues[CurrentMsgIdx].Events.RequiredEvent != '' &&
|
||||
!Dialogues[CurrentMsgIdx].bLooping)
|
||||
{
|
||||
bWaitingForEvent = !Dialogues[CurrentMsgIdx].bWasTriggered;
|
||||
}
|
||||
|
||||
if(!bWaitingForEvent)
|
||||
{
|
||||
if(bDebugDialogue)
|
||||
{
|
||||
log("----- DIALOGUE DEBUG ------ Showing Dialogue at index .. "@CurrentMsgIdx, 'Story_Debug');
|
||||
}
|
||||
|
||||
ShowDialogue(CurrentMsgIdx);
|
||||
if(CurrentMsgIdx + 1 < Dialogues.length )
|
||||
{
|
||||
bTraversing = true;
|
||||
|
||||
if(GetCurrentDisplayDur() > 0)
|
||||
{
|
||||
SetTimer(GetCurrentDisplayDur(),false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Timer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we're finished. Reset the actor */
|
||||
OnDialogueCompleted();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(bDebugDialogue)
|
||||
{
|
||||
log("----- DIALOGUE DEBUG ------ Freezing dialogue at index :"@CurrentMsgIdx@"for event : "@Dialogues[CurrentMsgIdx].Events.RequiredEvent, 'Story_Debug');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function OnDialogueCompleted()
|
||||
{
|
||||
bFinished = true;
|
||||
}
|
||||
|
||||
function Timer()
|
||||
{
|
||||
if(bTraversing)
|
||||
{
|
||||
bTraversing = false;
|
||||
|
||||
if(CurrentMsgIdx + 1 < Dialogues.length && !bRandomize)
|
||||
{
|
||||
if(!Dialogues[CurrentMsgIdx].bLooping)
|
||||
{
|
||||
CurrentMsgIdx ++ ;
|
||||
if(bDebugDialogue)
|
||||
{
|
||||
log("----- DIALOGUE DEBUG ------ Incrementing Dialogue Index .. ", 'Story_Debug');
|
||||
}
|
||||
|
||||
TraverseDialogue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function - calculates the amount of time a string should
|
||||
be displayed for based on its word length */
|
||||
|
||||
function float CalcDisplayTime(string InString)
|
||||
{
|
||||
local float TimePerWord;
|
||||
local array<string> Words;
|
||||
|
||||
TimePerWord = 0.5f;
|
||||
Split(InString," ",Words);
|
||||
|
||||
return FMax(Words.length * TimePerWord,3.f);
|
||||
}
|
||||
|
||||
function ShowDialogue(int DlgIndex)
|
||||
{
|
||||
local Controller C;
|
||||
local KFPlayerController_Story StoryPC;
|
||||
local string SpeakerName;
|
||||
local actor VoiceOverSource;
|
||||
local Material Portrait;
|
||||
local Pawn MyInstigator;
|
||||
|
||||
/* nothing to show, nothing to play ... early out */
|
||||
if(Dialogues[DlgIndex].Display.Dialogue_Text == "" &&
|
||||
Dialogues[DlgIndex].VoiceOver.VoiceOverSound == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (C = Level.ControllerList; C != None; C = C.NextController)
|
||||
{
|
||||
StoryPC = KFPlayerController_Story(C);
|
||||
if(StoryPC != none &&
|
||||
(Dialogues[DlgIndex].BroadcastScope != InstigatorOnly ||
|
||||
(DialogueInstigator != none && DialogueInstigator == C) ))
|
||||
{
|
||||
SpeakerName = Dialogues[DlgIndex].Display.Dialogue_Header ;
|
||||
Portrait = Dialogues[DlgIndex].Display.Portrait_Material ;
|
||||
|
||||
if(SpeakerName == "self")
|
||||
{
|
||||
SpeakerName = StoryPC.PlayerReplicationinfo.PlayerName ;
|
||||
Portrait = xPlayerReplicationInfo(StoryPC.PlayerReplicationInfo).Rec.Portrait;
|
||||
}
|
||||
|
||||
if(GetCurrentDisplayDur() > 0)
|
||||
{
|
||||
Dialogues[DlgIndex].EventListener.SetTimer(GetCurrentDisplayDur(),false);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDialogueDisplayComplete(DlgIndex);
|
||||
}
|
||||
|
||||
if(!SkipDialogue())
|
||||
{
|
||||
StoryPC.ClientShowStoryDialogue(name ,DlgIndex,GetCurrentDisplayDur());
|
||||
}
|
||||
|
||||
if ( !SkipDialogue() && Dialogues[DlgIndex].VoiceOver.VoiceOverSound != None )
|
||||
{
|
||||
/* attempt to play a spatialised sound from the source actor (if there is one) */
|
||||
VoiceOverSource = Dialogues[DlgIndex].VoiceOver.SourceActor ;
|
||||
if(VoiceOverSource != none)
|
||||
{
|
||||
VoiceOverSource.PlaySound(Dialogues[DlgIndex].VoiceOver.VoiceOverSound,SLOT_Talk,VoiceOverSource.SoundVolume,,VoiceOverSource.SoundRadius,VoiceOverSource.SoundPitch,VoiceOverSource.bFullVolume);
|
||||
}
|
||||
else /*otherwise just play a ClientSound */
|
||||
{
|
||||
StoryPC.ClientPlayStorySound(Dialogues[DlgIndex].VoiceOver.VoiceOverSound, 2.0, false );
|
||||
}
|
||||
}
|
||||
|
||||
if(Dialogues[DlgIndex].Events.DisplayingEvent != '')
|
||||
{
|
||||
MyInstigator = DialogueInstigator.Pawn;
|
||||
TriggerEvent(Dialogues[DlgIndex].Events.DisplayingEvent,self,MyInstigator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bool SkipDialogue()
|
||||
{
|
||||
return KFStoryGameInfo(Level.Game) != none && KFStoryGameInfo(Level.Game).bSkipDialogue;
|
||||
}
|
||||
|
||||
function float GetCurrentDisplayDur()
|
||||
{
|
||||
local float Duration,VODuration;
|
||||
|
||||
if( SkipDialogue())
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
Duration = CalcDisplayTime(Dialogues[CurrentMsgIdx].Display.Dialogue_Text);
|
||||
|
||||
/* Always make sure the text sticks around for at least as long as the VO */
|
||||
if(Dialogues[CurrentMsgIdx].VoiceOver.VoiceOverSound != none)
|
||||
{
|
||||
VODuration = Dialogues[CurrentMsgIdx].VoiceOver.VoiceOverSound.Duration;
|
||||
Duration = VODuration * 1.15; // Gamespeed is 1.1 so you always have to multiplay sound durations by 1.1. Adding a bit more buffer just in case - Ramm
|
||||
}
|
||||
|
||||
return Duration;
|
||||
}
|
||||
|
||||
function GetRequiredEvents( out array<Name> AllRequiredEvents)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for(i = 0 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
if(Dialogues[i].Events.RequiredEvent != '')
|
||||
{
|
||||
AllRequiredEvents[AllRequiredEvents.length] = Dialogues[i].Events.RequiredEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function GetDisplayEvents( out array<Name> AllDisplayEvents)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for(i = 0 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
if(Dialogues[i].Events.DisplayedEvent != '')
|
||||
{
|
||||
AllDisplayEvents[AllDisplayEvents.length] = Dialogues[i].Events.DisplayedEvent;
|
||||
}
|
||||
|
||||
if(Dialogues[i].Events.DisplayingEvent != '')
|
||||
{
|
||||
AllDisplayEvents[AllDisplayEvents.length] = Dialogues[i].Events.DisplayingEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function GetEvents(out array<name> TriggeredEvents, out array<name> ReceivedEvents)
|
||||
{
|
||||
local int i;
|
||||
|
||||
Super.GetEvents(TriggeredEvents,ReceivedEvents);
|
||||
|
||||
for(i = 0 ; i < Dialogues.length ; i ++)
|
||||
{
|
||||
/* Things I trigger */
|
||||
if(Dialogues[i].Events.DisplayedEvent != '')
|
||||
{
|
||||
TriggeredEvents[TriggeredEvents.length] = Dialogues[i].Events.DisplayedEvent;
|
||||
}
|
||||
if(Dialogues[i].Events.DisplayingEvent != '')
|
||||
{
|
||||
TriggeredEvents[TriggeredEvents.length] = Dialogues[i].Events.DisplayingEvent;
|
||||
}
|
||||
/* Things that trigger me*/
|
||||
if(Dialogues[i].Events.RequiredEvent != '')
|
||||
{
|
||||
ReceivedEvents[ReceivedEvents.length] = Dialogues[i].Events.RequiredEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DrawScale = 0.5
|
||||
|
||||
bDebugDialogue = true
|
||||
bNoDelete = true
|
||||
bCollideActors = true
|
||||
SkipDlgRange = 250
|
||||
|
||||
Texture = Texture 'KFStoryGame_Tex.Editor.KF_Dlgspot_Ico'
|
||||
}
|
||||
|
||||
65
kf_sources/KFStoryGame/Classes/KF_HUDStyleManager.uc
Normal file
65
kf_sources/KFStoryGame/Classes/KF_HUDStyleManager.uc
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_HUDStyleManager
|
||||
--------------------------------------------------------------
|
||||
|
||||
Placeable actor able to store multiple skin presets for the
|
||||
players HUD.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class KF_HUDStyleManager extends Info
|
||||
dependson(KFStoryGameInfo)
|
||||
placeable;
|
||||
|
||||
|
||||
|
||||
struct SConditionStyle
|
||||
{
|
||||
var() KFStoryGameInfo.SConditionHintInfoWorld Style_ObjCondition_World;
|
||||
var() KFStoryGameInfo.SConditionHintInfoHUD Style_ObjCondition_Screen;
|
||||
var() Color Condition_Clr;
|
||||
};
|
||||
|
||||
struct SObjectiveStyle
|
||||
{
|
||||
var() KFStoryGameInfo.SObjectiveHeaderInfo Header;
|
||||
var() KFStoryGameInfo.SObjectiveBackgroundInfo Background;
|
||||
var() KFStoryGameInfo.SVect2D Position;
|
||||
var() SConditionStyle Conditions;
|
||||
var() bool bOverride;
|
||||
};
|
||||
|
||||
|
||||
struct SMainHUDStyle
|
||||
{
|
||||
var() Material Ammo_Background;
|
||||
var() bool bOverride;
|
||||
};
|
||||
|
||||
struct SDialogueStyle
|
||||
{
|
||||
var() KFStoryGameInfo.SDialogueDisplayInfo Dialogue_Box;
|
||||
var() bool bOverride;
|
||||
};
|
||||
|
||||
struct SStylePreset
|
||||
{
|
||||
var() name StyleName;
|
||||
var() SDialogueStyle Dialogue;
|
||||
var() SObjectiveStyle Objectives;
|
||||
var() SMainHUDStyle MainHUD;
|
||||
};
|
||||
|
||||
|
||||
var() SStylePreset StylePreset;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bNoDelete = true
|
||||
}
|
||||
|
||||
51
kf_sources/KFStoryGame/Classes/KF_ObjectiveAction.uc
Normal file
51
kf_sources/KFStoryGame/Classes/KF_ObjectiveAction.uc
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_ObjectiveAction
|
||||
--------------------------------------------------------------
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_ObjectiveAction extends BaseObjectiveAction
|
||||
hidecategories(Object);
|
||||
|
||||
/* Reference to the Objective that this action belongs to */
|
||||
var private KF_StoryObjective ObjOwner;
|
||||
|
||||
/* Is this action currently being processed ? */
|
||||
var bool bActive;
|
||||
|
||||
function bool IsValidActionFor(KF_StoryObjective Obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function KF_StoryObjective GetObjOwner()
|
||||
{
|
||||
return ObjOwner;
|
||||
}
|
||||
|
||||
function SetObjOwner(Actor NewOwner)
|
||||
{
|
||||
ObjOwner = KF_StoryObjective(NewOwner);
|
||||
}
|
||||
|
||||
function ActionActivated(pawn ActivatingPlayer)
|
||||
{
|
||||
bActive = true;
|
||||
}
|
||||
function ActionDeActivated()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
bActive = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
849
kf_sources/KFStoryGame/Classes/KF_ObjectiveCondition.uc
Normal file
849
kf_sources/KFStoryGame/Classes/KF_ObjectiveCondition.uc
Normal file
|
|
@ -0,0 +1,849 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_ObjectiveCondition
|
||||
--------------------------------------------------------------
|
||||
|
||||
Object used to store gameplay conditions for KF_StoryObjectives
|
||||
Configured by level designers.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#exec OBJ LOAD FILE=KFStoryGame_Tex.utx
|
||||
|
||||
class KF_ObjectiveCondition extends Object
|
||||
abstract
|
||||
dependson(KFStoryGameInfo)
|
||||
hidecategories(Object);
|
||||
|
||||
|
||||
const HintCharLimit = 35;
|
||||
|
||||
|
||||
/* Pawn responsible for Activating and / or completing this condition. */
|
||||
var const name InstigatorName;
|
||||
|
||||
var bool bComplete,SavedbComplete;
|
||||
|
||||
var float LastActivatedTime;
|
||||
|
||||
var float LastRepTime;
|
||||
|
||||
/* Minimum time between client updates of condition data */
|
||||
var (Network) float ConditionRepInterval;
|
||||
|
||||
/* HUD properties ======================================================================
|
||||
=======================================================================================*/
|
||||
|
||||
/* HUD Properties that pertain to the world (Wisp trail, projected icons, etc.) */
|
||||
var (HUD) KFStoryGameInfo.SConditionHintInfoWorld HUD_World;
|
||||
|
||||
/* HUD Properties that pertain to the player's On-screen display */
|
||||
var (HUD) KFStoryGameInfo.SConditionHintInfoHUD HUD_Screen;
|
||||
|
||||
var float OldCompletionPct,NewCompletionPct;
|
||||
|
||||
var bool OldComplete,NewComplete;
|
||||
|
||||
var string OldDataString,NewDataString;
|
||||
|
||||
var vector OldWorldLoc,NewLocation;
|
||||
|
||||
|
||||
/* =====================================================================================
|
||||
=======================================================================================*/
|
||||
|
||||
var bool bActive,SavedbActive;
|
||||
|
||||
var bool bWasTriggered,SavedbWasTriggered;
|
||||
|
||||
var byte ConditionType; // 0 = failure, 1 = success , 2 = optional
|
||||
|
||||
|
||||
|
||||
/* An array that stores Condition dependencies.
|
||||
ie. We only want this condition to be considered for completion if the
|
||||
conditions in this list are already completed and share the same instigator as us.
|
||||
|
||||
an example of this would be a Key locked door */
|
||||
|
||||
var() array <KF_ObjectiveCondition> DependentConditions;
|
||||
|
||||
/* If true this objective cannot be 'uncompleted' once it is complete, without being reset */
|
||||
var() bool bCompleteOnce;
|
||||
|
||||
var bool bLockCompletion;
|
||||
|
||||
var bool bForceReliableUpdate;
|
||||
|
||||
/* Difficulty Modifiers ============================================================*/
|
||||
|
||||
enum EKFGameDifficulty
|
||||
{
|
||||
All,
|
||||
Beginner,
|
||||
Normal,
|
||||
Hard,
|
||||
Suicidal,
|
||||
HellOnEarth,
|
||||
};
|
||||
|
||||
/* Only use this condition above MinDifficulty and below MaxDifficulty */
|
||||
var(Difficulty) EKFGameDifficulty Difficulty_Min,Difficulty_Max;
|
||||
|
||||
|
||||
var(Difficulty) int PlayerCount_Min,PlayerCount_Max;
|
||||
|
||||
/* Scales the Condition's requirements based on the server's difficulty setting */
|
||||
var(Difficulty) KFStoryGameInfo.SConditionDifficultyScale Scale_GameDifficulty;
|
||||
|
||||
/* Scales the Condition's requirements based on the number of players on the server */
|
||||
var(Difficulty) float Scale_PlayerCount;
|
||||
|
||||
var private transient KF_StoryObjective ObjOwner;
|
||||
|
||||
/* =====================================================================================
|
||||
=======================================================================================*/
|
||||
|
||||
var(Events) array<KFStoryGameInfo.SObjectiveProgressEvent> ProgressEvents;
|
||||
|
||||
/* =====================================================================================
|
||||
=======================================================================================*/
|
||||
|
||||
var private KF_Objective_EventListener Eventlistener;
|
||||
|
||||
var(Events) name Tag;
|
||||
|
||||
var() KFStoryGameInfo.EConditionInitialState InitialState;
|
||||
|
||||
var() KFStoryGameInfo.EConditionActivationMethod ActivationMethod;
|
||||
|
||||
var() KFStoryGameInfo.EProgressImportance ProgressImportance;
|
||||
|
||||
var const name InitialWorldLocActorName, WorldLocActorName;
|
||||
|
||||
|
||||
/*========== AUDIO =====================================================================*/
|
||||
|
||||
var(Audio) sound Sound_Completion;
|
||||
|
||||
|
||||
function StoppedUsing(pawn User){}
|
||||
function StartedUsing(pawn User){}
|
||||
|
||||
function PostBeginPlay(KF_StoryObjective MyOwner)
|
||||
{
|
||||
SpawnEventListener(MyOwner);
|
||||
|
||||
// cache and clear.
|
||||
if(HUD_World.World_Location != none)
|
||||
{
|
||||
SetTargetActor(InitialWorldLocActorName,HUD_World.World_Location);
|
||||
SetTargetActor(WorldLocActorName,HUD_World.World_Location);
|
||||
HUD_World.World_Location = none;
|
||||
}
|
||||
}
|
||||
|
||||
function SaveState()
|
||||
{
|
||||
SavedbComplete = bComplete;
|
||||
SavedbActive = bActive;
|
||||
SavedbWasTriggered = bWasTriggered;
|
||||
}
|
||||
|
||||
function Actor GetTargetActor(name TargetName)
|
||||
{
|
||||
local Actor TargetActor;
|
||||
|
||||
EventListener.FindAssociatedActor(TargetName,TargetActor);
|
||||
return TargetActor;
|
||||
}
|
||||
|
||||
|
||||
function SetTargetActor(name NewTargetName, Actor NewValue)
|
||||
{
|
||||
Eventlistener.AddAssociatedActor(NewTargetName,NewValue);
|
||||
}
|
||||
|
||||
function ReleaseTargetActor(name ReleaseTargetName)
|
||||
{
|
||||
EventListener.RemoveAssociatedActor(ReleaseTargetname);
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(GetObjOwner().ActiveCheckPoint == none)
|
||||
{
|
||||
bWasTriggered = false;
|
||||
bActive = false;
|
||||
bComplete = false;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
bWasTriggered = SavedbWasTriggered;
|
||||
bActive = SavedbActive;
|
||||
bComplete = SavedbComplete;
|
||||
}
|
||||
|
||||
for(i = 0 ; i < ProgressEvents.Length ; i ++)
|
||||
{
|
||||
ProgressEvents[i].bWasTriggered = false;
|
||||
}
|
||||
|
||||
OldDataString = "";
|
||||
OldCompletionPct = 0.f;
|
||||
OldWorldLoc = vect(0,0,0);
|
||||
NewLocation = vect(0,0,0);
|
||||
bLockCompletion = false;
|
||||
}
|
||||
|
||||
function Trigger(actor Other, pawn EventInstigator)
|
||||
{
|
||||
if(ConditionIsValid())
|
||||
{
|
||||
SetTargetActor(InstigatorName,EventInstigator);
|
||||
|
||||
switch(ActivationMethod)
|
||||
{
|
||||
case TriggerToggled :
|
||||
if(!bActive)
|
||||
{
|
||||
// log("**********************************************");
|
||||
// log("Activating Condition By Trigger - :"@name);
|
||||
GetObjOwner().ActivateCondition(self);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// log("**********************************************");
|
||||
// log("Deactivating Condition By Trigger - :"@name);
|
||||
GetObjOwner().DeActivateCondition(self);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TriggerActivates :
|
||||
if(!bActive)
|
||||
{
|
||||
GetObjOwner().ActivateCondition(self);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TriggerDeActivates :
|
||||
if(bActive)
|
||||
{
|
||||
GetObjOwner().DeActivateCondition(self);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bActive)
|
||||
{
|
||||
bWasTriggered = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function bool ConditionIsRelevant()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function bool ConditionIsActive()
|
||||
{
|
||||
// log(self@"Owner : "@GetObjOwner().ObjectiveName@" Complete ? : "@bComplete@" Active ? : "@bActive,'Story_Debug');
|
||||
return GetObjOwner() != none && bActive && (!bCompleteOnce || !bComplete);
|
||||
}
|
||||
|
||||
/* Returns true if this condition should initialize automatically when its owning objective becomes active
|
||||
In most cases this will be true ... except for complex conditions which the LD intentionally wants to activate
|
||||
manually (after certain events in the mission , etc.)
|
||||
*/
|
||||
|
||||
function bool ShouldInitOnActivation()
|
||||
{
|
||||
local bool Result;
|
||||
|
||||
if(InitialState == Active ||
|
||||
(ActivationMethod == RandomlyActivate &&
|
||||
FRand() > 0.5)) // condition is valid for activation
|
||||
{
|
||||
Result = true;
|
||||
}
|
||||
|
||||
return Result && ConditionIsValid();
|
||||
}
|
||||
|
||||
/* Only returns true if this condition is valid for activation - based on various factors like Game Difficulty, Player Count, etc.
|
||||
*/
|
||||
|
||||
function bool ConditionIsValid()
|
||||
{
|
||||
local int NumPlayers;
|
||||
local float CurrentDifficulty,MaxDifficulty,MinDifficulty;
|
||||
local bool Result;
|
||||
|
||||
Result = true;
|
||||
|
||||
/* =============== Check Difficulty & Player Count validitiy ======*/
|
||||
|
||||
/* Make sure the values are in range first .. */
|
||||
PlayerCount_Min = Min(PlayerCount_Min,PlayerCount_Max);
|
||||
PlayerCount_Max = Max(PlayerCount_Max,PlayerCount_Min);
|
||||
|
||||
|
||||
if(GetObjOwner() != none)
|
||||
{
|
||||
NumPlayers = KFStoryGameInfo(GetObjOwner().Level.Game).GetTotalActivePlayers();
|
||||
CurrentDifficulty = GetObjOwner().Level.Game.GameDifficulty;
|
||||
}
|
||||
|
||||
if((PlayerCount_Max > 0 && NumPlayers > PlayerCount_Max) ||
|
||||
(PlayerCount_Min > 0 && NumPlayers < PlayerCount_Min))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(Difficulty_Max > 0)
|
||||
{
|
||||
switch(Difficulty_Max)
|
||||
{
|
||||
case Beginner : MaxDifficulty = 1.f ; break;
|
||||
case Normal : MaxDifficulty = 2.f ; break;
|
||||
case Hard : MaxDifficulty = 4.f ; break;
|
||||
case Suicidal : MaxDifficulty = 5.f ; break;
|
||||
case HellOnEarth : MaxDifficulty = 7.f ; break;
|
||||
}
|
||||
|
||||
Result = CurrentDifficulty <= MaxDifficulty ;
|
||||
}
|
||||
if(Difficulty_Min > 0)
|
||||
{
|
||||
switch(Difficulty_Min)
|
||||
{
|
||||
case Beginner : MinDifficulty = 1.f ; break;
|
||||
case Normal : MinDifficulty = 2.f ; break;
|
||||
case Hard : MinDifficulty = 4.f ; break;
|
||||
case Suicidal : MinDifficulty = 5.f ; break;
|
||||
case HellOnEarth : MinDifficulty = 7.f ; break;
|
||||
}
|
||||
|
||||
return Result && CurrentDifficulty >= MinDifficulty ;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* Returns a value that scales this condition's requirements based on the Game Difficulty setting of the server */
|
||||
function float GetGameDifficultyModifier()
|
||||
{
|
||||
local float CurrentDifficulty,DiffModifier;
|
||||
|
||||
CurrentDifficulty = GetObjOwner().Level.Game.GameDifficulty;
|
||||
DiffModifier = 1.f;
|
||||
|
||||
switch(CurrentDifficulty)
|
||||
{
|
||||
case 1 : DiffModifier = Scale_GameDifficulty.Scale_Beginner; break; // Beginner.
|
||||
case 3 : DiffModifier = Scale_GameDifficulty.Scale_Hard; break; // Hard.
|
||||
case 5 : DiffModifier = Scale_GameDifficulty.Scale_Suicidal; break; // Suicidal.
|
||||
case 7 : DiffModifier = Scale_GameDifficulty.Scale_HellOnEarth; break; // Hell On Earth.
|
||||
}
|
||||
|
||||
return DiffModifier;
|
||||
}
|
||||
|
||||
/* Returns a value that scales this condition's requirements based on the number of players on the server */
|
||||
function float GetPlayerCountModifier()
|
||||
{
|
||||
local int NumPlayers;
|
||||
|
||||
NumPlayers = KFStoryGameInfo(GetObjOwner().Level.Game).GetTotalActivePlayers();
|
||||
|
||||
if(NumPlayers <= 1)
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
return FMax(NumPlayers * Scale_PlayerCount, 1.f);
|
||||
}
|
||||
|
||||
function float GetTotalDifficultyModifier()
|
||||
{
|
||||
return GetGameDifficultyModifier() * GetPlayerCountModifier();
|
||||
}
|
||||
|
||||
function ConditionActivated(pawn ActivatingPlayer)
|
||||
{
|
||||
SetTargetActor(InstigatorName,ActivatingPlayer);
|
||||
|
||||
LastActivatedTime = GetObjOwner().Level.TimeSeconds;
|
||||
bActive = true;
|
||||
|
||||
if(GetTargetActor(InitialWorldLocActorName) != none)
|
||||
{
|
||||
SetTargetActor(WorldLocActorName,GetTargetActor(InitialWorldLocActorName));
|
||||
}
|
||||
|
||||
ReliableConditionUpdate();
|
||||
}
|
||||
|
||||
function ConditionDeActivated()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
function bool IsOptionalCondition()
|
||||
{
|
||||
return ConditionType == 2;
|
||||
}
|
||||
|
||||
|
||||
function SpawnEventListener(KF_StoryObjective MyOwner)
|
||||
{
|
||||
if(Eventlistener == none )
|
||||
{
|
||||
EventListener = MyOwner.Spawn(class 'KF_Objective_EventListener');
|
||||
EventListener.SetConditionOwner(self);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow Completion of this Condition
|
||||
always true unless there is an outstanding dependency */
|
||||
function bool AllowCompletion()
|
||||
{
|
||||
local int i;
|
||||
local bool Result;
|
||||
|
||||
Result = true;
|
||||
|
||||
for(i = 0 ; i < DependentConditions.length ; i ++)
|
||||
{
|
||||
if(!DependentConditions[i].bComplete ||
|
||||
!DependentConditions[i].FindInstigator(GetInstigatorList()))
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
|
||||
}
|
||||
|
||||
/* Some conditions may have multiple instigators */
|
||||
function bool FindInstigator(array<Pawn> TestInstigators)
|
||||
{
|
||||
local int i,idx;
|
||||
local array<Pawn> MyInstigatorList;
|
||||
|
||||
MyInstigatorList = GetInstigatorList();
|
||||
|
||||
for(i = 0 ; i < TestInstigators.length ; i ++)
|
||||
{
|
||||
for(idx = 0 ; idx < MyInstigatorList.length ; idx ++)
|
||||
{
|
||||
if(TestInstigators[i] == MyInstigatorList[idx])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function array<Pawn> GetInstigatorList()
|
||||
{
|
||||
local array<Pawn> Instigators;
|
||||
|
||||
Instigators[Instigators.length] = Pawn(GetTargetActor(InstigatorName));
|
||||
return Instigators;
|
||||
}
|
||||
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
local float PctComplete;
|
||||
|
||||
PctComplete = GetCompletionPct();
|
||||
TriggerProgressEvents(PctComplete);
|
||||
|
||||
if(!bComplete)
|
||||
{
|
||||
if(PctComplete >= 1.f &&
|
||||
AllowCompletion())
|
||||
{
|
||||
ConditionCompleted();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!bLockCompletion &&
|
||||
!bCompleteOnce &&
|
||||
PctComplete < 1.f)
|
||||
{
|
||||
bComplete = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Timed HUD Update - replicated , so do it only when the values actually change.*/
|
||||
ConditionTickHUDUpdate();
|
||||
}
|
||||
|
||||
/* Progress Event updates - Fired off at different stages in the condition's completion */
|
||||
function TriggerProgressEvents(float PctComplete)
|
||||
{
|
||||
local int EventIdx;
|
||||
|
||||
for(EventIdx = 0 ; EventIdx < ProgressEvents.length ; EventIdx ++)
|
||||
{
|
||||
if(PctComplete >= ProgressEvents[EventIdx].ProgressPct &&
|
||||
(!ProgressEvents[EventIdx].bWasTriggered ||
|
||||
(ProgressEvents[EventIdx].bReTriggerable &&
|
||||
PctComplete != ProgressEvents[EventIdx].LastTriggeredPct ) ) )
|
||||
{
|
||||
ProgressEvents[EventIdx].bWasTriggered = true;
|
||||
GetObjOwner().TriggerEvent( ProgressEvents[EventIdx].EventName,GetObjOwner(),Pawn(GetTargetActor(InstigatorName)));
|
||||
}
|
||||
|
||||
ProgressEvents[EventIdx].LastTriggeredPct = PctComplete;
|
||||
}
|
||||
}
|
||||
|
||||
function bool AllowConditionRepUpdate()
|
||||
{
|
||||
if( GetObjOwner().Level.TimeSeconds - LastRepTime < ConditionRepInterval ||
|
||||
(HUD_World.bHide && HUD_Screen.Screen_ProgressStyle == 0 ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Reliable HUD Update - Sends condition information to clients. Only used when a player
|
||||
absolutely MUST get accurate data from this condition.
|
||||
*/
|
||||
function ReliableConditionUpdate(optional KFPlayerController_Story TargetPlayer)
|
||||
{
|
||||
local KFPlayerController_Story StoryPC;
|
||||
local Controller C;
|
||||
local float CompletionPct;
|
||||
local string HUDHint;
|
||||
local Actor NewLocActor;
|
||||
|
||||
GetLocation(NewLocActor);
|
||||
CompletionPct = GetCompletionPct();
|
||||
|
||||
if(HUD_Screen.Screen_CountStyle != Hide_Counter)
|
||||
{
|
||||
HUDHint = GetDataString();
|
||||
}
|
||||
|
||||
/* We want to update a specific Client's HUD */
|
||||
if(TargetPlayer != none)
|
||||
{
|
||||
TargetPlayer.ReliableConditionUpdate(self,
|
||||
GetObjOwner(),
|
||||
CompletionPct,
|
||||
NewLocActor,
|
||||
HUDHint,
|
||||
bComplete);
|
||||
}
|
||||
else // update everyone at once
|
||||
{
|
||||
For( C=GetObjOwner().Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
StoryPC = KFPlayerController_Story(C);
|
||||
if(StoryPC != none)
|
||||
{
|
||||
StoryPC.ReliableConditionUpdate(self,
|
||||
GetObjOwner(),
|
||||
CompletionPct,
|
||||
NewLocActor,
|
||||
HUDHint,
|
||||
bComplete);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Replicates relevant info for this condition to clients
|
||||
VERY expensive - for this reason it is throttled and only
|
||||
set to replicate dirty values
|
||||
|
||||
@Todo - is there a more efficient way to do this ?
|
||||
|
||||
*/
|
||||
|
||||
function ConditionTickHUDUpdate()
|
||||
{
|
||||
local KFPlayerController_Story StoryPC;
|
||||
local Controller C;
|
||||
local bool bUpdateHUD;
|
||||
local Actor NewLocActor;
|
||||
|
||||
if((GetObjOwner().AllowConditionRepUpdate() && AllowConditionRepUpdate()) )
|
||||
{
|
||||
GetLocation(NewLocActor);
|
||||
|
||||
OldComplete = NewComplete;
|
||||
NewComplete = bComplete || !bActive;
|
||||
|
||||
OldDataString = NewDataString;
|
||||
|
||||
if(HUD_Screen.Screen_CountStyle != Hide_Counter)
|
||||
{
|
||||
NewDataString = GetDataString();
|
||||
}
|
||||
|
||||
OldCompletionPct = NewCompletionPct;
|
||||
NewCompletionPct = GetCompletionPct();
|
||||
|
||||
bUpdateHUD = NewCompletionPct != OldCompletionPct ||
|
||||
NewComplete != OldComplete ||
|
||||
NewDataString != OldDataString;
|
||||
|
||||
if(bUpdateHUD)
|
||||
{
|
||||
LastRepTime = GetObjOwner().Level.TimeSeconds;
|
||||
GetObjOwner().CurrentRepUpdates ++ ;
|
||||
|
||||
For( C=GetObjOwner().Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
StoryPC = KFPlayerController_Story(C);
|
||||
if(StoryPC != none)
|
||||
{
|
||||
if( bForceReliableUpdate )
|
||||
{
|
||||
StoryPC.ReliableConditionUpdate(self,
|
||||
GetObjOwner(),
|
||||
NewCompletionPct,
|
||||
NewLocActor,
|
||||
NewDataString,
|
||||
bComplete);
|
||||
}
|
||||
else
|
||||
{
|
||||
StoryPC.UnreliableConditionUpdate(self,
|
||||
GetObjOwner(),
|
||||
NewCompletionPct,
|
||||
NewLocActor,
|
||||
NewDataString,
|
||||
NewComplete);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set the 'bComplete' bool to notify the parent Objective that this Condition is complete */
|
||||
function ConditionCompleted()
|
||||
{
|
||||
local actor SourceActor;
|
||||
local Controller C;
|
||||
|
||||
/* NOTE - any completion event stuff should be done *Before* bComplete is marked true*/
|
||||
|
||||
if(Sound_Completion != none)
|
||||
{
|
||||
GetLocation(SourceActor);
|
||||
if(SourceActor != none &&
|
||||
SourceActor != GetObjOwner())
|
||||
{
|
||||
SourceActor.PlaySound(Sound_Completion,,SourceActor.SoundVolume,,SourceActor.SoundRadius,SourceActor.SoundPitch,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (C = GetObjOwner().Level.ControllerList; C != None; C = C.NextController)
|
||||
{
|
||||
if(PlayerController(C) != none)
|
||||
{
|
||||
PlayerController(C).ClientPlaySound(Sound_Completion,true,2.f,SLOT_Talk);
|
||||
}
|
||||
}
|
||||
// log("Warning - Attempted to play Completion sound for"@name@" with no Source Actor!",'Story_Debug');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bComplete = true;
|
||||
log("==============================================================================================", 'Story_Debug');
|
||||
log("============= "@self@" a condition of "@GetObjOwner().ObjectiveName@" was just marked complete. ", 'Story_Debug');
|
||||
|
||||
ReliableConditionUpdate();
|
||||
|
||||
}
|
||||
|
||||
/* Accessor functions ========================== */
|
||||
|
||||
function SetObjOwner(KF_StoryObjective NewOwner)
|
||||
{
|
||||
ObjOwner = NewOwner;
|
||||
}
|
||||
|
||||
function KF_StoryObjective GetObjOwner()
|
||||
{
|
||||
return ObjOwner;
|
||||
}
|
||||
|
||||
/* Returns a reference to the pawn which instigated this condition last */
|
||||
function Pawn GetInstigator()
|
||||
{
|
||||
return Pawn(GetTargetActor(InstigatorName));
|
||||
}
|
||||
|
||||
function int GetOwnerArrayIndex()
|
||||
{
|
||||
return GetObjOwner().FindIndexForCondition(self);
|
||||
}
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
return float(bComplete);
|
||||
}
|
||||
|
||||
function string GetDataString()
|
||||
{
|
||||
return "" ;
|
||||
}
|
||||
|
||||
/* Hint to display over the world icon */
|
||||
function string GetWorldHint()
|
||||
{
|
||||
return HUD_World.World_Hint ;
|
||||
}
|
||||
|
||||
function string GetHUDHint()
|
||||
{
|
||||
return ClampHUDHint(HUD_Screen.Screen_Hint);
|
||||
}
|
||||
|
||||
function string ClampHUDHint(string Hint)
|
||||
{
|
||||
if( Len(Hint) > HintCharLimit )
|
||||
{
|
||||
Hint = left(Hint,HintCharLimit);
|
||||
Hint $= "..";
|
||||
}
|
||||
|
||||
return Hint;
|
||||
}
|
||||
|
||||
function vector GetLocation(optional out Actor LocActor)
|
||||
{
|
||||
if(ConditionIsActive())
|
||||
{
|
||||
if(GetWorldLocActor(LocActor))
|
||||
{
|
||||
return LocActor.Location ;
|
||||
}
|
||||
|
||||
LocActor = GetObjOwner();
|
||||
return GetObjOwner().Location;
|
||||
}
|
||||
}
|
||||
|
||||
function bool GetWorldLocActor(out Actor LocActor)
|
||||
{
|
||||
local Actor HUDWorldActor;
|
||||
|
||||
HUDWorldActor = GetTargetActor(WorldLocActorName);
|
||||
|
||||
if(ConditionIsActive() &&
|
||||
HUDWorldActor != none &&
|
||||
!HUDWorldActor.bPendingDelete &&
|
||||
!HUDWorldActor.bDeleteMe)
|
||||
{
|
||||
LocActor = HUDWorldActor;
|
||||
return true; ;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function vector GetWhispLocation(optional out Actor LocActor)
|
||||
{
|
||||
return GetNearestPathNodeTo(GetLocation(LocActor)).Location;
|
||||
}
|
||||
|
||||
function bool ShouldShowWhispTrailFor(PlayerController C)
|
||||
{
|
||||
return HUD_World.bShowWhispTrail;
|
||||
}
|
||||
|
||||
function NavigationPoint GetNearestPathNodeTo( vector DesiredLocation)
|
||||
{
|
||||
local navigationpoint N,Closest;
|
||||
local float ClosestDistSq,DistSq;
|
||||
|
||||
for ( N=GetObjOwner().Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
|
||||
{
|
||||
DistSq = VSizeSquared(N.Location - DesiredLocation) ;
|
||||
if(Closest == none || DistSq < ClosestDistSq)
|
||||
{
|
||||
Closest = N ;
|
||||
ClosestDistSq = DistSq;
|
||||
}
|
||||
}
|
||||
|
||||
return Closest;
|
||||
}
|
||||
|
||||
/* TimeFormatting string function Copied from Scoreboard.uc */
|
||||
|
||||
function String FormatTime( int Seconds )
|
||||
{
|
||||
local int Minutes, Hours;
|
||||
local String Time;
|
||||
|
||||
if( Seconds > 3600 )
|
||||
{
|
||||
Hours = Seconds / 3600;
|
||||
Seconds -= Hours * 3600;
|
||||
|
||||
Time = Hours$":";
|
||||
}
|
||||
Minutes = Seconds / 60;
|
||||
Seconds -= Minutes * 60;
|
||||
|
||||
if( Minutes >= 10 )
|
||||
Time = Time $ Minutes $ ":";
|
||||
else
|
||||
Time = Time $ "0" $ Minutes $ ":";
|
||||
|
||||
if( Seconds >= 10 )
|
||||
Time = Time $ Seconds;
|
||||
else
|
||||
Time = Time $ "0" $ Seconds;
|
||||
|
||||
return Time;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
WorldLocActorName = "HUDWorldActor"
|
||||
InitialWorldLocActorName = "InitialHUDWorldActor"
|
||||
InstigatorName = "Instigator"
|
||||
|
||||
ConditionRepInterval = 0.5
|
||||
InitialState = Active
|
||||
|
||||
Scale_GameDifficulty=(Scale_Beginner=1,Scale_Hard=1,Scale_Suicidal=1,Scale_HellOnEarth=1)
|
||||
Scale_PlayerCount=1.f
|
||||
|
||||
HUD_World=(World_Clr=(R=255,G=50,B=50,A=255),Whisp_Clr=(R=255,G=50,B=50,A=255),World_Texture=none/*TexOscillator'KFStoryGame_Tex.HUD.ObjArrow_osc'*/,bHide=false,World_Texture_Scale=1.f)
|
||||
HUD_Screen=(Screen_Clr=(R=255,G=50,B=50,A=255),Screen_ProgressStyle=HDS_Combination,bShowStrikethrough=true,FontScale=Font_Medium,Screen_ProgressBarBG=Texture'KFStoryGame_Tex.HUD.HUd_Rectangel_W_Stroke_Neutral',Screen_ProgressBarFill=Texture 'KFStoryGame_Tex.HUD.Hud_Rectangle_W_Stroke_Fill')
|
||||
}
|
||||
|
||||
|
||||
106
kf_sources/KFStoryGame/Classes/KF_Objective_EventListener.uc
Normal file
106
kf_sources/KFStoryGame/Classes/KF_Objective_EventListener.uc
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_Objective_EventListener
|
||||
--------------------------------------------------------------
|
||||
|
||||
Bzsic Proxy actor which receives trigger events for Objective conditions.
|
||||
|
||||
As of 10/17/13 we are also using this to store actor references for conditions.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class KF_Objective_EventListener extends Actor;
|
||||
|
||||
// Condition which this actor stores actor References for.
|
||||
var private KF_ObjectiveCondition ConditionOwner;
|
||||
|
||||
// A struct which contains a reference to an actor.
|
||||
// Objects cannot have references to actors which are being garbage collected
|
||||
// or the game will crash. So we cache them here instead.
|
||||
|
||||
struct SConditionActorReference
|
||||
{
|
||||
var Actor TargetActor;
|
||||
var name ActorName;
|
||||
};
|
||||
|
||||
// This array contains a list of all the Actors which are relevant to its ConditionOwner.
|
||||
var protected array<SConditionActorReference> AssociatedActors;
|
||||
|
||||
// This function is called to cache an Actor that is relevant to ConditionOwner.
|
||||
function AddAssociatedActor(name NewActorName,Actor NewActor )
|
||||
{
|
||||
local int Index;
|
||||
|
||||
if(!FindAssociatedActor(NewActorName,,Index))
|
||||
{
|
||||
AssociatedActors.Length = AssociatedActors.length + 1;
|
||||
AssociatedActors[AssociatedActors.length - 1].TargetActor = NewActor;
|
||||
AssociatedActors[AssociatedActors.length - 1].ActorName = NewActorName;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssociatedActors[Index].TargetActor = NewActor;
|
||||
}
|
||||
}
|
||||
|
||||
// This function is called to remove an Actor associated with ConditionOwner from the AssociatedActors cache.
|
||||
function RemoveAssociatedActor(name ActorToRemove)
|
||||
{
|
||||
local int Index;
|
||||
|
||||
if(FindAssociatedActor(ActorToRemove,,Index))
|
||||
{
|
||||
AssociatedActors.Remove(Index,1);
|
||||
}
|
||||
}
|
||||
|
||||
// Search the AssociatedActors cache by name.
|
||||
function bool FindAssociatedActor( name TargetActorName, optional out Actor TargetActor , optional out int Index)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for(i = 0 ; i < AssociatedActors.length ; i ++)
|
||||
{
|
||||
if(AssociatedActors[i].ActorName != '' &&
|
||||
AssociatedActors[i].ActorName == TargetActorName)
|
||||
{
|
||||
TargetActor = AssociatedActors[i].TargetActor;
|
||||
Index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function SetConditionOwner(KF_ObjectiveCondition NewOwner)
|
||||
{
|
||||
ConditionOwner = NewOwner;
|
||||
Tag = ConditionOwner.Tag;
|
||||
}
|
||||
|
||||
function KF_ObjectiveCondition GetConditionOwner()
|
||||
{
|
||||
return ConditionOwner;
|
||||
}
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
if(ConditionOwner != none)
|
||||
{
|
||||
ConditionOwner.Trigger(Other,EventInstigator);
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bstatic = false
|
||||
bHidden = true
|
||||
bNoDelete = false
|
||||
RemoteRole = Role_None
|
||||
}
|
||||
29
kf_sources/KFStoryGame/Classes/KF_PawnWelder.uc
Normal file
29
kf_sources/KFStoryGame/Classes/KF_PawnWelder.uc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/* a welder that can be used on human pawns to heal them */
|
||||
|
||||
class KF_PawnWelder extends Welder;
|
||||
|
||||
#exec OBJ LOAD FILE=KF_Weapons_Trip_T.utx
|
||||
|
||||
|
||||
simulated function Tick(float dt)
|
||||
{
|
||||
local KF_BreakerBoxNPC Breaker;
|
||||
|
||||
Super.Tick(dt);
|
||||
|
||||
if(WeldFire(FireMode[FireModeArray]).LastHitActor != none)
|
||||
{
|
||||
Breaker = KF_BreakerBoxNPC(WeldFire(FireMode[FireModeArray]).LastHitActor);
|
||||
if(Breaker != none)
|
||||
{
|
||||
ScreenWeldPercent = (Breaker.Health / Breaker.HealthMax) * 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
// AmmoRegenRate=20.000000
|
||||
FireModeClass(0)=Class'PawnWeldFire'
|
||||
}
|
||||
248
kf_sources/KFStoryGame/Classes/KF_PlaceableStoryPickup.uc
Normal file
248
kf_sources/KFStoryGame/Classes/KF_PlaceableStoryPickup.uc
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryInvPickupSpot
|
||||
--------------------------------------------------------------
|
||||
|
||||
When placing Inventory Pickups in Story maps this actor should be used
|
||||
in place of KF_StoryInventoryPickups.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_PlaceableStoryPickup extends xPickupBase
|
||||
hidecategories(PickupBase);
|
||||
|
||||
/* Icon to render for this Pickup on the holding player's HUD */
|
||||
var(Pickup_HUD) Material HUDMaterial;
|
||||
|
||||
/* Icon to render over top of this Pickup while it's sitting on the ground */
|
||||
var(Pickup_HUD) Material GroundMaterial;
|
||||
|
||||
/* If true, don't perform line traces to determine if we should render the GroundMaterial (setting this true is an optimization) */
|
||||
var(Pickup_HUD) bool bRenderIconThroughWalls;
|
||||
|
||||
/* Modifier to apply to the holding player's groundspeed */
|
||||
var(Pickup_PawnModifiers) float MovementSpeedModifier;
|
||||
|
||||
var(Pickup_Feedback) localized string Message_Dropped; // Human readable description when dropped.
|
||||
|
||||
var(Pickup_Feedback) localized string Message_PickedUp;
|
||||
|
||||
var(Pickup_Feedback) localized string Message_Use;
|
||||
|
||||
var(Pickup_Audio) Sound Sound_Dropped,Sound_PickedUp;
|
||||
|
||||
var(Pickup_3P) vector Attachment_Offset;
|
||||
|
||||
var(Pickup_3P) name Attachment_Bone;
|
||||
|
||||
var(Pickup_3P) rotator Attachment_Rotation;
|
||||
|
||||
var(Pickup_1P) bool bRender1PMesh;
|
||||
|
||||
/* When holding this item, display it with an 'X-Ray' shader in first person */
|
||||
var(Pickup_1P) bool bUseFirstPersonXRayEffect;
|
||||
|
||||
var(Pickup_1P) rotator ViewRotationOffset;
|
||||
|
||||
var(Pickup_1P) vector ViewLocationOffset;
|
||||
|
||||
/* Multiplies the height of the player's jumpZ by this amount */
|
||||
var(Pickup_PawnModifiers) float JumpZModifier;
|
||||
|
||||
/* List of weapons which cannot be used when this Item is carrieed */
|
||||
var(Pickup_Restrictions) array< Class<Weapon> > Weapons_Restricted;
|
||||
|
||||
/* List of weapons which can *only* be used when this item is carried */
|
||||
var(Pickup_Restrictions) array < Class<Weapon> > Weapons_Allowed;
|
||||
|
||||
/* Changes the amount of interest ZEDs will show in the player holding this item */
|
||||
var(Pickup_PawnModifiers) float AIThreatModifier;
|
||||
|
||||
/* Number of items of this class which can be held by a pawn at once */
|
||||
var(Pickup_Restrictions) int MaxHeldCopies;
|
||||
|
||||
/* Number of Inventory blocks this item takes up of the holder's weight allowance */
|
||||
var(Pickup_Restrictions) int InventoryWeight;
|
||||
|
||||
/* Determines when the pickup actor should be spawned for this pickupspot */
|
||||
enum EPickupSpawnMethod
|
||||
{
|
||||
Spawn_OnMapLoad,
|
||||
Spawn_OnMatchBegin,
|
||||
Spawn_OnTrigger,
|
||||
};
|
||||
|
||||
var(Pickup_Spawning) EPickupSpawnMethod SpawnMethod;
|
||||
|
||||
var KF_StoryInventoryPickup MyStoryPickup;
|
||||
|
||||
struct SCarriedEvent
|
||||
{
|
||||
var() name EventName;
|
||||
var() float TriggerInterval;
|
||||
var() int NumRepeats;
|
||||
var int NumTimesTriggered;
|
||||
var float LastTriggerTime;
|
||||
};
|
||||
|
||||
var(Events) array<SCarriedEvent> CarriedEvents;
|
||||
|
||||
var(Events) name DroppedEvent;
|
||||
|
||||
/* UUs per second this pickup should travel at when tossed by a player */
|
||||
var(Pickup_Tossing) float Pickup_TossVelocity;
|
||||
|
||||
/* If true, orient this pickup's toss direction from the players camera instead of his pawn rotation */
|
||||
var(Pickup_Tossing) bool bDropFromCameraLoc;
|
||||
|
||||
/* Type of damage this pickup does when it smacks into something :- ) */
|
||||
var(Pickup_Tossing) class<DamageType> ImpactDamType;
|
||||
|
||||
var(Pickup_Tossing) int ImpactDamage;
|
||||
|
||||
|
||||
simulated event PostBeginPlay()
|
||||
{
|
||||
if(SpawnMethod == Spawn_OnMapLoad)
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
}
|
||||
}
|
||||
|
||||
function MatchStarting()
|
||||
{
|
||||
Super.MatchStarting();
|
||||
|
||||
if(SpawnMethod == Spawn_OnMatchBegin)
|
||||
{
|
||||
SpawnPickup();
|
||||
}
|
||||
}
|
||||
|
||||
event Trigger( Actor Other, Pawn EventInstigator )
|
||||
{
|
||||
Super.Trigger(Other,EventInstigator);
|
||||
|
||||
if(SpawnMethod == Spawn_OnTrigger)
|
||||
{
|
||||
SpawnPickup();
|
||||
}
|
||||
}
|
||||
|
||||
simulated function CopyPropertiesTo(KF_StoryInventoryPickup NewPickup)
|
||||
{
|
||||
// log("*******************************************************");
|
||||
// log("Client Copy properties from : "@self@" to - :"@NewPickup);
|
||||
|
||||
NewPickup.StoryPickupBase = self;
|
||||
|
||||
NewPickup.Event = event;
|
||||
NewPickup.tag = tag;
|
||||
NewPickup.MaxHeldCopies = MaxHeldCopies;
|
||||
NewPickup.SetCollisionSize(CollisionRadius,CollisionHeight);
|
||||
NewPickup.PrePivot = PrePivot;
|
||||
NewPickup.PlacedRotation = Rotation;
|
||||
NewPickup.SetDrawType(DrawType);
|
||||
NewPickup.SetStaticMesh(StaticMesh);
|
||||
NewPickup.LinkMesh(Mesh);
|
||||
NewPickup.SetDrawScale(DrawScale);
|
||||
NewPickup.SetDrawScale3D(DrawScale3D);
|
||||
NewPickup.bRenderIconThroughWalls = bRenderIconThroughWalls;
|
||||
NewPickup.bUseFirstPersonXRayEffect = bUseFirstPersonXRayEffect;
|
||||
NewPickup.MovementSpeedModifier = MovementSpeedModifier;
|
||||
NewPickup.AIThreatModifier = AIThreatModifier;
|
||||
NewPickup.Weight = InventoryWeight;
|
||||
NewPickup.default.DroppedMessage = Message_Dropped;
|
||||
NewPickup.default.UseMeMessage = Message_Use;
|
||||
NewPickup.default.PickupMessage = Message_PickedUp;
|
||||
NewPickup.CarriedMaterial = HUDMaterial ;
|
||||
Newpickup.GroundMaterial = GroundMaterial;
|
||||
NewPickup.PickupSound = Sound_PickedUp;
|
||||
NewPickup.DroppedSound = Sound_Dropped;
|
||||
NewPickup.UV2Texture = UV2Texture;
|
||||
NewPickup.bRender1PMesh = bRender1PMesh;
|
||||
NewPickup.ViewLocationOffset = ViewLocationOffset;
|
||||
NewPickup.ViewRotationOffset = ViewRotationOffset;
|
||||
NewPickup.Pickup_TossVelocity = Pickup_TossVelocity;
|
||||
NewPickup.bDropFromCameraLoc = bDropFromCameraLoc;
|
||||
NewPickup.ImpactDamType = ImpactDamType;
|
||||
NewPickup.ImpactDamage = ImpactDamage;
|
||||
|
||||
// Lighting
|
||||
|
||||
NewPickup.LightType = LightType;
|
||||
NewPickup.LightCone = LightCone;
|
||||
NewPickup.LightBrightness = LightBrightness;
|
||||
NewPickup.LightRadius = LightRadius;
|
||||
NewPickup.bUseDynamicLights = bUseDynamicLights;
|
||||
NewPickup.LightSaturation = LightSaturation;
|
||||
NewPickup.bDynamicLight = bDynamicLight;
|
||||
NewPickup.AmbientGlow = AmbientGlow;
|
||||
NewPickup.LightHue = LightHue;
|
||||
|
||||
NewPickup.bLightChanged = true;
|
||||
}
|
||||
|
||||
function SpawnPickup()
|
||||
{
|
||||
if( myPickUp != none || PowerUp == None || Level.NetMode == NM_Client )
|
||||
return;
|
||||
|
||||
myPickUp = Spawn(PowerUp,,,Location,Rotation);
|
||||
if(myPickup != none)
|
||||
{
|
||||
myPickUp.PickUpBase = self;
|
||||
|
||||
MyStoryPickup = KF_StoryInventoryPickup(myPickup);
|
||||
if(MyStoryPickup != none)
|
||||
{
|
||||
CopyPropertiesTo(MyStoryPickup);
|
||||
}
|
||||
}
|
||||
|
||||
if (myMarker != None)
|
||||
{
|
||||
myMarker.markedItem = myPickUp;
|
||||
myMarker.ExtraCost = ExtraPathCost;
|
||||
if (myPickUp != None)
|
||||
myPickup.MyMarker = MyMarker;
|
||||
}
|
||||
else log("No marker for "$self);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ImpactDamType = class 'Engine.Crushed'
|
||||
ImpactDamage = 0
|
||||
|
||||
Pickup_TossVelocity = 250
|
||||
bRender1PMesh = true
|
||||
bStatic=false // to receive events
|
||||
bRenderIconThroughWalls = true
|
||||
bHidden = true
|
||||
bUseDynamicLights = true
|
||||
bNetInitialRotation = true
|
||||
bNoDelete = true
|
||||
|
||||
DrawType=DT_StaticMesh
|
||||
PrePivot=(X=0,Y=0,Z=10)
|
||||
DrawScale = 1
|
||||
StaticMesh = StaticMesh 'DetailSM.Crates.WoodBox_B'
|
||||
|
||||
CollisionHeight = 10
|
||||
CollisionRadius = 30
|
||||
|
||||
Message_Use = "Press USE key to Pick up"
|
||||
|
||||
MovementSpeedModifier = 1.f
|
||||
JumpZModifier = 1.f
|
||||
AIThreatModifier = 1.f
|
||||
|
||||
PowerUp = class 'KF_StoryInventoryPickup'
|
||||
|
||||
Sound_Dropped = Sound'Inf_Player.RagdollImpacts.BodyImpact'
|
||||
Sound_PickedUp = Sound 'KF_AxeSnd.Axe_Select'
|
||||
}
|
||||
792
kf_sources/KFStoryGame/Classes/KF_StoryCheckPointVolume.uc
Normal file
792
kf_sources/KFStoryGame/Classes/KF_StoryCheckPointVolume.uc
Normal file
|
|
@ -0,0 +1,792 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryCheckPointVolume
|
||||
--------------------------------------------------------------
|
||||
|
||||
Volume used to control spawning of players in story maps.
|
||||
|
||||
When active, only those player starts inside the bounds of the volume are considered
|
||||
valid spawn points. Can also be configured to force the respawn of dead (out of lives) players.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class KF_StoryCheckPointVolume extends PhysicsVolume
|
||||
hidecategories(PhysicsVolume,Collision,Brush,Advanced,Force,Karma,Lighting,LightColor,Movement,Sound,Volume,Display,VolumeFog) ;
|
||||
|
||||
|
||||
/* prints debug text */
|
||||
var bool bDebugCheckpoint;
|
||||
|
||||
/* if true this checkpoint will begin play active */
|
||||
var(StoryCheckPoint) bool bStartEnabled;
|
||||
|
||||
/* If true, touching (or triggering) this checkpoint will restart all dead players at one of the playerstarts inside the volume's bounds */
|
||||
var(StoryCheckPoint) bool bRespawnPlayers;
|
||||
|
||||
/* If true, this scripted action will respawn bot players as well as humans . Only used if bRespawnPlayers is true*/
|
||||
var(StoryCheckPoint) bool bIncludeBots;
|
||||
|
||||
/* true if CheckPointActivated() was called and this volume is the current spawn-checkpoint for players*/
|
||||
var bool bIsActive;
|
||||
|
||||
/* if true, CheckPointActivated() will only be called when the entire team is inside the Volume */
|
||||
var(StoryCheckPoint) bool bRequiresWholeTeam;
|
||||
|
||||
/* Only relevant if bRespawn players is true. In addition to respawning dead players when Activated this volume will also auto-respawn everyone when their whole team wipes out */
|
||||
var(StoryCheckPoint) bool bRespawnOnWipe;
|
||||
|
||||
/* Event that triggers when a team that was wiped out is given a 'second chance' by this Volume. Only relevant if bRespawnOnWipe is true */
|
||||
var(Events) array<name> SecondChanceEvents;
|
||||
|
||||
/* array of additional events this checkpoint can trigger for use in maps with complex trigger setups */
|
||||
var(Events) array<name> ActivationEvents;
|
||||
|
||||
/* Delay before dead players are actually restarted after the Checkpoint activates */
|
||||
var(StoryCheckPoint) float RespawnDelay;
|
||||
|
||||
/* %of Max Health a player spawns with when this checkpoint brings him back to life. */
|
||||
var(StoryCheckPoint) float RespawnHealthModifier;
|
||||
|
||||
/* if true , 'RespawnHealthModifier' becomes cumulative each time a player respawns at this checkpoint. ie. if a player dies twice with a value of 0.75, his starting health would be 56*/
|
||||
var(StoryCheckPoint) bool bCumulativeHealthModifier;
|
||||
|
||||
/* same as above, but used if the LD wants to reset only specific actors in the map */
|
||||
var(Team_Restart) array<actor> CheckPointResetActors;
|
||||
|
||||
/* for cases where the LD wants to reset all actors in the map of a particular class *Except* some specific actors ..*/
|
||||
var(Team_Restart) array<actor> ResetExcludeActors;
|
||||
|
||||
|
||||
var name RestartFromObjective;
|
||||
|
||||
/* players who wipe out will respawn at this specific checkpoint, if assigned */
|
||||
var(Team_Restart) string RestartFromCheckPoint;
|
||||
|
||||
/* Object reference to the CheckPoint who's name we specified above */
|
||||
var KF_StoryCheckPointVolume ForcedRestartCheckPoint;
|
||||
|
||||
/* Removes all dropped / thrown weapon pickups from play when a team is restarted at this checkpoint */
|
||||
var(Team_Restart) bool bRemoveDroppedWeapons;
|
||||
|
||||
/* true while the Respawn Timer is running but RespawnPlayers() has not yet been called */
|
||||
var bool bPendingRespawn;
|
||||
|
||||
/* true while the team is wiped out completely and is waiting to be restarted from this checkpoint */
|
||||
var bool bPendingFullRestart;
|
||||
|
||||
/* Spawned to control timing of Player respawns. Necessary because volumes are Static & can't run their own timers */
|
||||
var RespawnTimer RespawnDelayTimer;
|
||||
|
||||
/* Cached reference to the player who last activated this Checkpoint */
|
||||
var Controller ActivatingPlayer;
|
||||
|
||||
/* Cached reference to the player who was last respawned by this Checkpoint */
|
||||
var Controller LastRespawnedPlayer;
|
||||
|
||||
/* If true, teleport stragglers to a playerstart inside this volume */
|
||||
var(Stragglers) bool bTeleportStragglers;
|
||||
|
||||
/* Max distance a player can be from this volume before being consider a straggler */
|
||||
var(Stragglers) float TeleportStragglerDist;
|
||||
|
||||
// if bTeleportStragglers, any living players not inside this volume will be teleported to a playerstart in the checkpoitn volume.
|
||||
var(Stragglers) const Volume TeleportExclusionVolume;
|
||||
|
||||
/* If true this checkpoint can only be set as the active checkpoint in the map a single time
|
||||
Should probably be set true by default as most story maps will probably have a linear progression.
|
||||
*/
|
||||
|
||||
var(StoryCheckPoint) bool bShowActivationMsg;
|
||||
|
||||
var(StoryCheckPoint) bool bSingleActivationOnly;
|
||||
|
||||
/* FriendlyName */
|
||||
var(StoryCheckPoint) string CheckPointName;
|
||||
|
||||
/* Cached reference to Story gameinfo to cut down on typecasting */
|
||||
var KFStoryGameInfo StoryGI;
|
||||
|
||||
/* used to save the current state of Dialogue at the time a checkpoint is activated so that it can be returned to later if a team restarts */
|
||||
struct SDialogueState
|
||||
{
|
||||
var KF_DialogueSpot DialogueActor;
|
||||
var int SavedIndex;
|
||||
var array<byte> DialogueTriggerStates;
|
||||
};
|
||||
|
||||
var array<SDialogueState> SavedDialogue;
|
||||
|
||||
|
||||
enum ECheckPointTriggerType
|
||||
{
|
||||
CTT_Touch,
|
||||
CTT_Trigger,
|
||||
};
|
||||
|
||||
/* do we want this checkpoint to become active when remotely triggered, or on player touch ? */
|
||||
var (StoryCheckPoint) ECheckPointTriggerType CheckPointTriggerType;
|
||||
|
||||
var array<PlayerStart> PSList;
|
||||
|
||||
function Reset()
|
||||
{
|
||||
LastRespawnedPlayer = none;
|
||||
ActivatingPlayer = none;
|
||||
bPendingRespawn = false;
|
||||
bIsActive = false;
|
||||
}
|
||||
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
local NavigationPoint N;
|
||||
local PlayerStart PS;
|
||||
local KF_DialogueSpot DlgSpot;
|
||||
|
||||
if( Level.NetMode==NM_Client )
|
||||
return;
|
||||
|
||||
/* No KFO Gametype, no Initialization */
|
||||
StoryGI = KFStoryGameInfo(Level.Game);
|
||||
if(StoryGI == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
For( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
|
||||
{
|
||||
PS = PlayerStart(N);
|
||||
if( PS!=None )
|
||||
{
|
||||
if(Encompasses(PS) )
|
||||
{
|
||||
PSList[PSList.Length] = PS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(RestartFromCheckPoint != "" &&
|
||||
RestartFromCheckPoint != CheckPointName &&
|
||||
StoryGI != none )
|
||||
{
|
||||
ForcedRestartCheckPoint = StoryGI.FindCheckPointNamed(RestartFromCheckPoint);
|
||||
}
|
||||
|
||||
// cache all the DialogueSpots in the map - we'll need this to store the states for each one
|
||||
foreach DynamicActors(class 'KF_DialogueSpot', DlgSpot)
|
||||
{
|
||||
SavedDialogue.length = SavedDialogue.length + 1;
|
||||
SavedDialogue[SavedDialogue.length-1].DialogueActor = DlgSpot;
|
||||
SavedDialogue[SavedDialogue.length-1].DialogueTriggerStates.length = DlgSpot.Dialogues.length ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Wrapper for checking if this volume can grant second chances to teams that wipe out during story gameplay */
|
||||
function bool CanGrantSecondChances()
|
||||
{
|
||||
local bool Result;
|
||||
|
||||
if(ForcedRestartCheckPoint != none)
|
||||
{
|
||||
Result = true;//ForcedRestartCheckPoint.IsActiveRespawnPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = IsActiveRespawnPoint();
|
||||
}
|
||||
|
||||
|
||||
if(!Result)
|
||||
{
|
||||
if(ForcedRestartCheckPoint != none)
|
||||
{
|
||||
log("Forced Restart CheckPoint : "@ForcedRestartCheckPoint.CheckPointName@" for - "@CheckPointName@" is unable to Respawn players at the moment. It is probably inactive . ");
|
||||
}
|
||||
else
|
||||
{
|
||||
log("CheckPoint : "@CheckPointName@"is unable to Respawn players at the moment. It is probably inactive . ");
|
||||
}
|
||||
}
|
||||
return Result ;
|
||||
}
|
||||
|
||||
function bool IsActiveRespawnPoint()
|
||||
{
|
||||
return bIsActive && bRespawnPlayers && bRespawnOnWipe /*&& !bPendingRespawn*/;
|
||||
}
|
||||
|
||||
/* Respawns all dead players in the game when they wipe out - Returns true if successful */
|
||||
|
||||
function bool GrantASecondChance(out KF_StoryCheckPointVolume RespawnPoint)
|
||||
{
|
||||
if(CanGrantSecondChances())
|
||||
{
|
||||
RespawnPoint = self;
|
||||
|
||||
if(ForcedRestartCheckPoint != none)
|
||||
{
|
||||
RespawnPoint = ForcedRestartCheckPoint ;
|
||||
}
|
||||
|
||||
bPendingFullRestart = true;
|
||||
RespawnPoint.Reset() ;
|
||||
RespawnPoint.Instigator = Instigator;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function UpdateSpawnAvailability()
|
||||
{
|
||||
local NavigationPoint N;
|
||||
local PlayerStart PS;
|
||||
local bool bEnableMe;
|
||||
|
||||
if( PSList.Length>0 )
|
||||
{
|
||||
For( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
|
||||
{
|
||||
PS = PlayerStart(N);
|
||||
if(PS != none)
|
||||
{
|
||||
// log("Updating spawn availability for "@self@" - "@PS@".bEnabled = "@bEnableMe);
|
||||
bEnableMe = bIsActive && PStartBelongsToThisVolume(PS);
|
||||
PS.bEnabled = bEnableMe ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Warning - No Playerstarts associated with "@self@": Respawns will fail.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function bool PStartBelongsToThisVolume( PlayerStart TestSpot)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for( i = 0 ; i < PSList.length; i ++)
|
||||
{
|
||||
if(PSList[i] == TestSpot)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Encompasses(TestSpot);
|
||||
}
|
||||
|
||||
/* CTT_Touch*/
|
||||
|
||||
simulated event PawnEnteredVolume(Pawn Other)
|
||||
{
|
||||
if(CheckPointTriggerType == CTT_Touch &&
|
||||
(Other.Controller != none && Other.Controller.bIsPlayer) /*&& Other.IsPlayerPawn()*/) // <- IsPlayerPawn() returns true in Monster.uc ...derp
|
||||
{
|
||||
CheckPointActivated(Other,false,bShowActivationMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/* CTT_Trigger*/
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
if(CheckPointTriggerType == CTT_Trigger/* && EventInstigator != none &&
|
||||
EventInstigator.IsPlayerPawn()*/)
|
||||
{
|
||||
CheckPointActivated(EventInstigator,false,bShowActivationMsg);
|
||||
}
|
||||
}
|
||||
|
||||
function ResetPlayerCheckPointStats()
|
||||
{
|
||||
local Controller C;
|
||||
local KFPlayerController_Story PC;
|
||||
|
||||
For ( C= Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
PC = KFPlayerController_Story(C);
|
||||
if(PC != none)
|
||||
{
|
||||
PC.NumCheckPointRespawns = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function int GetNumPlayersInVolume()
|
||||
{
|
||||
local int Num;
|
||||
local Controller C;
|
||||
|
||||
for ( C=Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if(C.bIsPlayer && C.Pawn != none)
|
||||
{
|
||||
if(Encompasses(C.Pawn))
|
||||
{
|
||||
Num ++ ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// log("NUM PLAYERS IN VOLUME : "@Num);
|
||||
|
||||
return Num;
|
||||
}
|
||||
|
||||
/* Tracks the current state of game Objectives & Dialogue at the time this checkpoint was activated */
|
||||
function SaveStoryState()
|
||||
{
|
||||
local int i,idx;
|
||||
local KF_DialogueSpot Dlg;
|
||||
local bool bJumpingForward;
|
||||
local int NextEventIdx;
|
||||
local name NextSortedObj;
|
||||
local Controller C;
|
||||
local KFPlayerController_Story SPC;
|
||||
|
||||
|
||||
if(bPendingFullRestart)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the LD hasn't provided a forced Objective to restart from, use whatever was current at the time of activation */
|
||||
if(RestartFromObjective == '' )
|
||||
{
|
||||
if(StoryGI.CurrentObjective != none && StoryGI.CurrentObjective.bCheckPointable)
|
||||
{
|
||||
RestartFromObjective = StoryGI.CurrentObjective.ObjectiveName;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if there's no current objective - the next objective is probably bManualActivate , so we're at a gap between obj's.
|
||||
In this case we can just use the LastObjective and jump one forward. */
|
||||
|
||||
NextSortedObj = StoryGI.SortedObjectives[ Min( StoryGI.CurrentObjectiveIdx + 1 ,StoryGI.SortedObjectives.length - 1 ) ].ObjectiveName ;
|
||||
log(" No current Objective .. Checkpoint will restart from Next sorted objective : "@NextSortedObj,'Story_Debug');
|
||||
RestartFromObjective = NextSortedObj;
|
||||
bJumpingForward = true;
|
||||
}
|
||||
|
||||
for(i = 0 ; i < StoryGI.AllObjectives.length ; i ++)
|
||||
{
|
||||
if(StoryGI.AllObjectives[i].ObjectiveName == RestartFromObjective)
|
||||
{
|
||||
StoryGI.AllObjectives[i].SetCheckPoint(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
StoryGI.AllObjectives[i].ClearCheckPoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0 ; i < SavedDialogue.length ; i ++)
|
||||
{
|
||||
Dlg = SavedDialogue[i].DialogueActor ;
|
||||
if(Dlg != none)
|
||||
{
|
||||
NextEventIdx = Dlg.GetNextDlgRequiredEventIdx(Dlg.CurrentMsgIdx) ;
|
||||
if(bJumpingForward && NextEventIdx > 0)
|
||||
{
|
||||
SavedDialogue[i].SavedIndex = NextEventIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
SavedDialogue[i].SavedIndex = Dlg.CurrentMsgIdx ;
|
||||
}
|
||||
|
||||
if(Dlg.bDebugDialogue)
|
||||
{
|
||||
log("----- DIALOGUE DEBUG ------ Saving Dialogue Index of : "@Dlg@" At : "@SavedDialogue[i].SavedIndex, 'Story_Debug' );
|
||||
}
|
||||
|
||||
for(idx = 0 ; idx < SavedDialogue[i].DialogueTriggerStates.length ; idx ++ )
|
||||
{
|
||||
SavedDialogue[i].DialogueTriggerStates[idx] = byte(Dlg.Dialogues[idx].bWasTriggered) ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// store players current equipment and cash amounts so we can restore it all when they spawn from this checkpoint
|
||||
for (C = Level.ControllerList; C != None; C = C.NextController)
|
||||
{
|
||||
SPC = KFPlayerController_Story(C);
|
||||
if(SPC != none)
|
||||
{
|
||||
SPC.SaveLoadOut();
|
||||
}
|
||||
|
||||
if(KF_StoryNPC(C.Pawn) != none)
|
||||
{
|
||||
KF_StoryNPC(C.Pawn).SaveHealthState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ModifyPlayer( pawn aPlayer)
|
||||
{
|
||||
local float CheckPointHealthModifier;
|
||||
local KFPlayerController_Story SPC;
|
||||
|
||||
SPC = KFPlayerController_Story(aPlayer.Controller);
|
||||
if(SPC == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(bRespawnOnWipe)
|
||||
{
|
||||
aPlayer.Health = SPC.SavedHealth;
|
||||
aPlayer.ShieldStrength = SPC.SavedArmor;
|
||||
SPC.PlayerReplicationInfo.Score = SPC.SavedCash;
|
||||
}
|
||||
|
||||
if (RespawnHealthModifier != 1.f )
|
||||
{
|
||||
CheckPointHealthModifier = RespawnHealthModifier ;
|
||||
if(bCumulativeHealthModifier)
|
||||
{
|
||||
CheckpointHealthModifier = CheckPointHealthModifier ** SPC.NumCheckPointRespawns ;
|
||||
}
|
||||
|
||||
aPlayer.Health = Max(aPlayer.Health * CheckPointHealthModifier,1) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function int GetSavedDialogueIndexFor(KF_DialogueSpot DialogueSpot , out array<byte> WasTriggeredArray)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(DialogueSpot == none)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( i = 0 ; i < SavedDialogue.length ; i ++)
|
||||
{
|
||||
if(SavedDialogue[i].DialogueActor != none &&
|
||||
SavedDialogue[i].DialogueActor == DialogueSpot)
|
||||
{
|
||||
WasTriggeredArray = SavedDialogue[i].DialogueTriggerStates ;
|
||||
return SavedDialogue[i].SavedIndex ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when this volume has been set as the new active checkpoint zone in the map
|
||||
Enables encompassed playerstarts & disables all others.
|
||||
*/
|
||||
|
||||
function CheckPointActivated( Pawn CheckPointInstigator, bool bForceActivate, optional bool bShowMessage)
|
||||
{
|
||||
local KF_StoryCheckPointVolume OldCheckpoint;
|
||||
local Controller C;
|
||||
|
||||
/* Check for a human controlled pawn */
|
||||
if(CheckPointInstigator.Controller != none)
|
||||
{
|
||||
ActivatingPlayer = CheckPointInstigator.Controller;
|
||||
if(ActivatingPlayer != none && PlayerController(ActivatingPlayer) != none &&
|
||||
ActivatingPlayer.Pawn != none )
|
||||
{
|
||||
Instigator = ActivatingPlayer.Pawn ;
|
||||
}
|
||||
}
|
||||
|
||||
if(!bForceActivate &&
|
||||
bRequiresWholeTeam &&
|
||||
GetNumPlayersInVolume() < StoryGI.GetTotalActivePlayers())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!bIsActive || bForceActivate || !bSingleActivationOnly)
|
||||
{
|
||||
log("===============================================",'Story_Debug');
|
||||
log("CheckPointActivated! - "@CheckPointName,'Story_Debug');
|
||||
|
||||
bIsActive = true;
|
||||
|
||||
if(!bPendingFullRestart)
|
||||
{
|
||||
TriggerActivationEvents();
|
||||
|
||||
if(bRespawnOnWipe)
|
||||
{
|
||||
SaveStoryState();
|
||||
}
|
||||
}
|
||||
|
||||
if(StoryGI != none)
|
||||
{
|
||||
OldCheckPoint = StoryGI.CurrentCheckPoint ;
|
||||
StoryGI.CurrentCheckPoint = self ;
|
||||
|
||||
for ( C=Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if(KFPlayerController_Story(C) != none)
|
||||
{
|
||||
KFPlayerController_Story(C).CurrentCheckPoint = self;
|
||||
}
|
||||
}
|
||||
|
||||
if(bShowMessage)
|
||||
{
|
||||
BroadcastLocalizedMessage( StoryGI.default.CheckPointMessageClass , 0, ActivatingPlayer.PlayerReplicationinfo, None, self );
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSpawnAvailability();
|
||||
ResetPlayerCheckpointStats();
|
||||
|
||||
if( bRespawnPlayers )
|
||||
{
|
||||
DelayedRespawnDeadPlayers();
|
||||
}
|
||||
|
||||
if( bTeleportstragglers)
|
||||
{
|
||||
TeleportLivingPlayers();
|
||||
}
|
||||
|
||||
if(Instigator == none)
|
||||
{
|
||||
log("Warning - No human instigator found when Activating "@self@". Some actors require a human instigator to trigger successfully . (Movers) ");
|
||||
}
|
||||
|
||||
if(bDebugCheckPoint)
|
||||
{
|
||||
PrintDebugText(ActivatingPlayer.PlayerReplicationInfo.PlayerName@"activated"@CheckPointName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fire off a set of events when this checkpoint is activated */
|
||||
|
||||
function TriggerActivationEvents()
|
||||
{
|
||||
local int i;
|
||||
|
||||
TriggerEvent(Event,self, Instigator);
|
||||
|
||||
for(i = 0 ; i < ActivationEvents.length ; i ++)
|
||||
{
|
||||
TriggerEvent(ActivationEvents[i],self,Instigator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function DelayedRespawnDeadPlayers()
|
||||
{
|
||||
if(!bPendingRespawn)
|
||||
{
|
||||
bPendingRespawn = true;
|
||||
|
||||
if ( RespawnDelayTimer == None )
|
||||
{
|
||||
RespawnDelayTimer = spawn(class'RespawnTimer', self);
|
||||
if(RespawnDelayTimer != none)
|
||||
{
|
||||
RespawnDelayTimer.TimerFrequency = RespawnDelay ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RespawnDelayTimer.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from ReSpawnTimer.Timer() - notification that the timer expired
|
||||
and it is now time to perform the actual respawn.*/
|
||||
|
||||
function RespawnTimerPop()
|
||||
{
|
||||
RespawnDeadPlayers();
|
||||
|
||||
/* if this is a full-team-restart, we need to reset certain actors in the map
|
||||
as well - Notify the gameinfo that this would be a good time to do that*/
|
||||
if(StoryGI != none && StoryGI.bPendingTeamRespawn)
|
||||
{
|
||||
StoryGI.bPendingTeamRespawn = false ;
|
||||
TriggerActivationEvents();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Brings bOutLives players back from the dead. They will spawn at one of the player starts inside this volume's bounds */
|
||||
|
||||
function RespawnDeadPlayers()
|
||||
{
|
||||
local Controller C;
|
||||
local KFPlayerController KFPC;
|
||||
local PlayerController PC;
|
||||
local KFPlayerReplicationInfo KFPRI;
|
||||
|
||||
bPendingRespawn = false;
|
||||
|
||||
For ( C= Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if ( C.PlayerReplicationInfo != none )
|
||||
{
|
||||
/* I'm guessing we are still using Perks in Story mode ? ... will leave this in for now */
|
||||
KFPC = KFPlayerController(C);
|
||||
if ( KFPC != none )
|
||||
{
|
||||
KFPRI = KFPlayerReplicationInfo(C.PlayerReplicationinfo);
|
||||
if ( KFPRI != none )
|
||||
{
|
||||
KFPC.bChangedVeterancyThisWave = false;
|
||||
|
||||
if ( KFPRI.ClientVeteranSkill != KFPC.SelectedVeterancy )
|
||||
{
|
||||
KFPC.SendSelectedVeterancyToServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(C.PlayerReplicationInfo.bOnlySpectator ||
|
||||
!C.PlayerReplicationInfo.bOutOfLives ||
|
||||
(C.PlayerReplicationInfo.bBot && !bIncludeBots))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
C.PlayerReplicationInfo.bOutOfLives = false;
|
||||
C.PlayerReplicationInfo.NumLives = 0;
|
||||
|
||||
PC = PlayerController(C);
|
||||
if( PC != none )
|
||||
{
|
||||
PC.GotoState('PlayerWaiting');
|
||||
PC.SetViewTarget(C);
|
||||
PC.ClientSetBehindView(false);
|
||||
PC.bBehindView = False;
|
||||
// PC.ClientSetViewTarget(C.Pawn); <- that's all well and good but .. At this point 'C' has no pawn ... Gonna move this down after RestartPlayer()
|
||||
}
|
||||
|
||||
if(KFPlayerController_Story(C) != none)
|
||||
{
|
||||
KFPLayerController_Story(C).NumCheckPointRespawns ++ ;
|
||||
}
|
||||
|
||||
LastRespawnedPlayer = C;
|
||||
|
||||
// Make sure the dude we're respawning hast at least some cash.
|
||||
C.PlayerReplicationInfo.Score = Max(KFGameType(Level.Game).MinRespawnCash, int(C.PlayerReplicationInfo.Score));
|
||||
C.ServerReStartPlayer();
|
||||
|
||||
if(PC != none && PC.Pawn != none)
|
||||
{
|
||||
PC.ClientSetViewTarget(PC.Pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LastRespawnedPlayer = none;
|
||||
|
||||
/* Full Checkpoint restart (everyone was wiped out) */
|
||||
if(bPendingFullRestart && StoryGI != none)
|
||||
{
|
||||
bPendingFullRestart = false;
|
||||
StoryGI.NotifyTeamRestarted();
|
||||
}
|
||||
}
|
||||
|
||||
/* Teleports all living players in the map (outside of the volume) to a playerstart in this volume. */
|
||||
|
||||
function TeleportLivingPlayers()
|
||||
{
|
||||
local NavigationPoint TeleportSpot;
|
||||
local Controller C;
|
||||
local bool bTeleportMe;
|
||||
|
||||
For ( C= Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
bTeleportMe = false;
|
||||
|
||||
if ( C.PlayerReplicationInfo != none )
|
||||
{
|
||||
if(C.bIsPlayer &&
|
||||
!C.PlayerReplicationInfo.bOutOfLives &&
|
||||
!C.PlayerReplicationInfo.bOnlySpectator &&
|
||||
C.Pawn != none && C.Pawn.Health > 0 &&
|
||||
C.Pawn.PhysicsVolume != self )
|
||||
{
|
||||
if(TeleportExclusionVolume != none)
|
||||
{
|
||||
bTeleportMe = !TeleportExclusionVolume.Encompasses(C.Pawn);
|
||||
}
|
||||
else
|
||||
{
|
||||
bTeleportMe = VSize(C.Pawn.Location - Location) >= TeleportStragglerDist;
|
||||
}
|
||||
|
||||
if(bTeleportMe)
|
||||
{
|
||||
TeleportSpot = Level.Game.FindPlayerStart(C,C.GetTeamNum());
|
||||
if(TeleportSpot != none)
|
||||
{
|
||||
C.Pawn.SetLocation(TeleportSpot.Location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function PrintDebugText( string Message)
|
||||
{
|
||||
local Controller C;
|
||||
local PlayerController P;
|
||||
|
||||
for ( C=Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
P = PlayerController(C);
|
||||
if( P != None )
|
||||
{
|
||||
P.TeamMessage(C.PlayerReplicationInfo, Message, 'CriticalEvent');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
CheckPointTriggerType = CTT_Touch ;
|
||||
bRespawnPlayers = true
|
||||
bRespawnOnWipe = true
|
||||
bIncludeBots = true
|
||||
bDebugCheckPoint = false
|
||||
RespawnDelay = 2.f
|
||||
RespawnHealthModifier = 1.0
|
||||
bCumulativeHealthModifier = true
|
||||
bSingleActivationOnly = true
|
||||
CheckPointName = "a checkpoint"
|
||||
|
||||
|
||||
TeleportStragglerDist = 2000
|
||||
bTeleportStragglers = false
|
||||
|
||||
bRemoveDroppedWeapons = true
|
||||
bShowActivationMsg = true
|
||||
|
||||
bStatic = false // needs to be non-static or it won't receive trigger events
|
||||
}
|
||||
58
kf_sources/KFStoryGame/Classes/KF_StoryElevator.uc
Normal file
58
kf_sources/KFStoryGame/Classes/KF_StoryElevator.uc
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
class KF_StoryElevator extends Mover;
|
||||
|
||||
var array<KF_StoryElevator_Door> Doors;
|
||||
|
||||
|
||||
// Elevator stopped. Detach the doors */
|
||||
function FinishNotify()
|
||||
{
|
||||
Super.FinishNotify();
|
||||
DetachDoors();
|
||||
}
|
||||
|
||||
function NotifyDoorsClosed()
|
||||
{
|
||||
if(!bInterpolating)
|
||||
{
|
||||
AttachDoors();
|
||||
Trigger(self,none);
|
||||
}
|
||||
}
|
||||
|
||||
function DetachDoors()
|
||||
{
|
||||
local int i;
|
||||
for(i = 0 ; i < Doors.length ; i ++)
|
||||
{
|
||||
Doors[i].DetachFromElevator();
|
||||
Doors[i].Trigger(self,none);
|
||||
}
|
||||
}
|
||||
|
||||
function AttachDoors()
|
||||
{
|
||||
local int i;
|
||||
for(i = 0 ; i < Doors.length ; i ++)
|
||||
{
|
||||
Doors[i].AttachToElevator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
state() TriggerToggle
|
||||
{
|
||||
function Reset()
|
||||
{
|
||||
super.Reset();
|
||||
|
||||
// Reset instantly
|
||||
SetResetStatus( true );
|
||||
GotoState( 'TriggerToggle', 'Close' );
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MoverEncroachType=ME_CrushWhenEncroach
|
||||
InitialState="TriggerToggle"
|
||||
}
|
||||
101
kf_sources/KFStoryGame/Classes/KF_StoryElevator_Door.uc
Normal file
101
kf_sources/KFStoryGame/Classes/KF_StoryElevator_Door.uc
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
class KF_StoryElevator_Door extends Mover;
|
||||
|
||||
var KF_StoryElevator MyElevator;
|
||||
|
||||
var() name ElevatorTag;
|
||||
|
||||
var vector InitialClosedLoc,InitialBasePos;
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
foreach DynamicActors(class 'KF_StoryElevator', MyElevator, ElevatorTag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
InitialBasePos = BasePos;
|
||||
|
||||
if(MyElevator != none)
|
||||
{
|
||||
MyElevator.Doors[MyElevator.Doors.length] = self;
|
||||
}
|
||||
}
|
||||
|
||||
// when the doors close, Base on and then move the elevator */
|
||||
function FinishedClosing()
|
||||
{
|
||||
Super.FinishedClosing();
|
||||
|
||||
if(MyElevator != none)
|
||||
{
|
||||
InitialClosedLoc = Location;
|
||||
MyElevator.NotifyDoorsClosed();
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle when triggered.
|
||||
state() TriggerToggle
|
||||
{
|
||||
event Trigger( Actor Other, Pawn EventInstigator )
|
||||
{
|
||||
/* elevator is in motion. would be a bad time to open the doors. */
|
||||
if(MyElevator != none && MyElevator.bInterpolating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Super.Trigger(Other,EventInstigator);
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
super.Reset();
|
||||
|
||||
DetachFromElevator(true);
|
||||
|
||||
// Reset instantly
|
||||
SetResetStatus( true );
|
||||
GotoState( 'TriggerToggle', 'Close' );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function AttachToElevator()
|
||||
{
|
||||
SetPhysics(PHYS_None);
|
||||
bHardAttach = true;
|
||||
SetBase(MyElevator);
|
||||
}
|
||||
|
||||
function DetachFromElevator(optional bool bReset)
|
||||
{
|
||||
if(bReset)
|
||||
{
|
||||
ResetKeyPositions();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateKeyPositions();
|
||||
}
|
||||
|
||||
SetPhysics(default.Physics);
|
||||
SetBase(none);
|
||||
bHardAttach = false;
|
||||
}
|
||||
|
||||
function UpdateKeyPositions()
|
||||
{
|
||||
BasePos.Z = Location.Z ;
|
||||
}
|
||||
|
||||
function ResetKeyPositions()
|
||||
{
|
||||
BasePos = InitialBasePos;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MoverEncroachType=ME_IgnoreWhenEncroach
|
||||
InitialState="TriggerToggle"
|
||||
}
|
||||
84
kf_sources/KFStoryGame/Classes/KF_StoryGRI.uc
Normal file
84
kf_sources/KFStoryGame/Classes/KF_StoryGRI.uc
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryGRI
|
||||
--------------------------------------------------------------
|
||||
|
||||
Custom GamereplicationInfo class for use in Story mode
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class KF_StoryGRI extends KFGameReplicationinfo;
|
||||
|
||||
|
||||
var private KF_StoryObjective CurrentObjective;
|
||||
|
||||
var private Material VictorySplashMaterial;
|
||||
|
||||
var private Material DefeatSplashMaterial;
|
||||
|
||||
var private KF_HUDStyleManager HUDStyleManager;
|
||||
|
||||
var private KF_StoryObjective DebugTargetObj;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if(Role == ROLE_Authority && bNetDirty)
|
||||
CurrentObjective,DebugTargetObj;
|
||||
|
||||
reliable if( Role == ROLE_Authority && bNetInitial)
|
||||
HUDStyleManager,VictorySplashMaterial,DefeatSplashMaterial;
|
||||
}
|
||||
|
||||
/* accessor for retrieving the current Objective set in the gameinfo */
|
||||
|
||||
simulated function KF_StoryObjective GetCurrentObjective()
|
||||
{
|
||||
return CurrentObjective;
|
||||
}
|
||||
|
||||
simulated function KF_StoryObjective GetDebugTargetObjective()
|
||||
{
|
||||
return DebugTargetObj;
|
||||
}
|
||||
|
||||
simulated function KF_HUDStyleManager GetHUDStyleManager()
|
||||
{
|
||||
return HUDStyleManager;
|
||||
}
|
||||
|
||||
simulated function Material GetVictorySplashMaterial()
|
||||
{
|
||||
return VictorySplashMaterial;
|
||||
}
|
||||
|
||||
simulated function Material GetDefeatSplashMaterial()
|
||||
{
|
||||
return DefeatSplashMaterial;
|
||||
}
|
||||
|
||||
function SetHUDStyleManager(KF_HUDStyleManager NewManager)
|
||||
{
|
||||
HUDStyleManager = NewManager;
|
||||
}
|
||||
|
||||
function SetDefeatMaterial(Material NewMat)
|
||||
{
|
||||
DefeatSplashMaterial = NewMat;
|
||||
}
|
||||
|
||||
function SetVictoryMaterial( Material NewMat)
|
||||
{
|
||||
VictorySplashMaterial = NewMat;
|
||||
}
|
||||
function SetCurrentObjective(KF_StoryObjective NewObjective)
|
||||
{
|
||||
CurrentObjective = NewObjective;
|
||||
}
|
||||
function SetDebugTargetObj(KF_StoryObjective NewDebugTarget)
|
||||
{
|
||||
DebugTargetObj = NewDebugTarget;
|
||||
}
|
||||
470
kf_sources/KFStoryGame/Classes/KF_StoryInventoryItem.uc
Normal file
470
kf_sources/KFStoryGame/Classes/KF_StoryInventoryItem.uc
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryInventoryItem
|
||||
--------------------------------------------------------------
|
||||
|
||||
Base class for Objective-driven inventory items which players can
|
||||
hold on their pawns.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_StoryInventoryItem extends Inventory
|
||||
dependson(KF_PlaceableStoryPickup);
|
||||
|
||||
/* Number of items of this class which can be held by a pawn at once */
|
||||
var int MaxHeldCopies;
|
||||
|
||||
var Material CarriedMaterial;
|
||||
|
||||
/* Icon to render over top of this Pickup while it's sitting on the ground */
|
||||
var Material GroundMaterial;
|
||||
|
||||
var float MovementSpeedModifier;
|
||||
|
||||
var class<DamageType> ImpactDamType;
|
||||
|
||||
var int ImpactDamage;
|
||||
|
||||
var rotator ViewRotationOffset;
|
||||
|
||||
var vector ViewLocationOffset;
|
||||
|
||||
/* If we want the pawn to go a specific speed when carrying this item (ignoring all other modifiers) , here's where we do it */
|
||||
var float ForcedGroundSpeed;
|
||||
|
||||
var bool bUseForcedGroundSpeed;
|
||||
|
||||
var float Pickup_TossVelocity;
|
||||
|
||||
var bool bDropFromCameraLoc;
|
||||
|
||||
var bool bRender1PMesh;
|
||||
|
||||
var float JumpZModifier;
|
||||
|
||||
var StaticMesh PickupSM;
|
||||
|
||||
var KF_PlaceableStoryPickup StoryPickupBase;
|
||||
|
||||
var name DroppedEvent;
|
||||
|
||||
var int Weight;
|
||||
|
||||
/* Changes the amount of interest ZEDs will show in the player holding this item */
|
||||
var float AIThreatModifier;
|
||||
|
||||
var name InvAttachmentBone;
|
||||
|
||||
/* When holding this item, display it with an 'X-Ray' shader in first person */
|
||||
var bool bUseFirstPersonXRayEffect;
|
||||
|
||||
/* List of weapons which cannot be used when this Item is carrieed */
|
||||
var array< Class<Weapon> > AllowedWeapons;
|
||||
|
||||
/* List of weapons which can *only* be used when this item is carried */
|
||||
var array < Class<Weapon> > RestrictedWeapons;
|
||||
|
||||
var array<KF_PlaceableStoryPickup.SCarriedEvent> CarriedEvents;
|
||||
|
||||
/* Disable the bCollideActors property of pickups spawned by this Item when they are created */
|
||||
var bool bDisableCollisionOnDrop;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if( Role==ROLE_Authority)
|
||||
MovementSpeedModifier,CarriedMaterial,ClientGiveTo,AllowHoldWeapon,StoryPickupBase,bRender1PMesh,bUseFirstPersonXRayEffect;
|
||||
|
||||
}
|
||||
|
||||
function GiveTo( pawn Other, optional Pickup Pickup )
|
||||
{
|
||||
Super.GiveTo(Other,Pickup);
|
||||
AttachToPawn(Instigator);
|
||||
ClientGiveTo(Other,Pickup);
|
||||
UpdateHeldMaterial(Other,CarriedMaterial);
|
||||
|
||||
if ( KFHumanPawn_Story( Other ) != none)
|
||||
{
|
||||
KFHumanPawn_Story( Other ).SetHasStoryItem( true );
|
||||
}
|
||||
}
|
||||
|
||||
/* Updates the Material which floats over the pawns head to this icon' Mat */
|
||||
function UpdateHeldMaterial(Pawn Holder, Material NewMat)
|
||||
{
|
||||
local KF_StoryPRI PRI;
|
||||
|
||||
PRI = KF_StoryPRI(Holder.PlayerReplicationInfo);
|
||||
if(PRI != none)
|
||||
{
|
||||
PRI.SetFloatingIconMat(NewMat);
|
||||
PRI.NetupdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
}
|
||||
|
||||
function Tick(float DeltaTime)
|
||||
{
|
||||
TriggerHeldEvents();
|
||||
}
|
||||
|
||||
function TriggerHeldEvents()
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(Instigator != none )
|
||||
{
|
||||
for(i = 0 ; i < CarriedEvents.length ; i ++)
|
||||
{
|
||||
if((CarriedEvents[i].NumRepeats == 0 ||
|
||||
CarriedEvents[i].NumTimesTriggered < CarriedEvents[i].NumRepeats) &&
|
||||
Level.TimeSeconds - CarriedEvents[i].LastTriggerTime >= CarriedEvents[i].TriggerInterval)
|
||||
{
|
||||
CarriedEvents[i].NumTimesTriggered ++ ;
|
||||
CarriedEvents[i].LastTriggerTime = Level.TimeSeconds;
|
||||
|
||||
TriggerEvent(CarriedEvents[i].EventName,self,Instigator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
simulated function ClientGiveTo(pawn Other,Pickup OwningPickup)
|
||||
{
|
||||
Instigator = Other;
|
||||
|
||||
if(KFHumanPawn_Story(Other) != none &&
|
||||
Other.Weapon != none &&
|
||||
!AllowHoldWeapon(Other.Weapon))
|
||||
{
|
||||
Other.PendingWeapon = KFHumanPawn_Story(Other).FindUseableWeaponFor(self);
|
||||
if(Other.PendingWeapon != none)
|
||||
{
|
||||
Other.PendingWeapon.ClientWeaponSet(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Render first person Model for Inventory item */
|
||||
simulated event RenderOverlays( canvas Canvas)
|
||||
{
|
||||
local int i;
|
||||
local int NumSkins;
|
||||
local vector ViewLoc, Locoffset;
|
||||
local Rotator ViewRot,RotOffset,PawnRot;
|
||||
|
||||
/* Orient the model to the holder's camera and draw it */
|
||||
|
||||
if(bRender1PMesh &&
|
||||
Instigator != none && PlayerController(Instigator.Controller) != none &&
|
||||
!PlayerController(Instigator.Controller).bBehindView)
|
||||
{
|
||||
/* X-Ray vision effect */
|
||||
|
||||
NumSkins = 3;
|
||||
Skins.length = Max(Skins.length,NumSkins);
|
||||
|
||||
for(i = 0 ; i < Skins.length ; i ++)
|
||||
{
|
||||
if(bUseFirstPersonXRayEffect)
|
||||
{
|
||||
Skins[i] = Shader 'KFStoryGame_Tex.Shaders.SeethruPickup_shdr' ;
|
||||
}
|
||||
}
|
||||
|
||||
if(StoryPickupBase != none)
|
||||
{
|
||||
LocOffset = StoryPickupBase.ViewLocationOffset;
|
||||
RotOffset = StoryPickupbase.ViewRotationOffset;
|
||||
}
|
||||
|
||||
PawnRot = Instigator.Rotation;
|
||||
ViewRot = Instigator.GetViewRotation() ;
|
||||
ViewLoc = (Instigator.Location + PlayerController(Instigator.Controller).CalcViewLocation) /2 ;
|
||||
|
||||
SetLocation(ViewLoc + (vector(ViewRot) * (CollisionRadius + Instigator.CollisionRadius)));
|
||||
SetRotation(ViewRot);
|
||||
SetRelativeLocation(Location + LocOffset);
|
||||
SetRelativeRotation(ViewRot + RotOffset);
|
||||
|
||||
Canvas.DrawActor(None, false, true); // clear Z Buffer.
|
||||
bDrawingFirstPerson = true;
|
||||
Canvas.DrawActor(self, false, false, 90.f);
|
||||
bDrawingFirstPerson = false;
|
||||
}
|
||||
}
|
||||
|
||||
function AttachToPawn(Pawn P)
|
||||
{
|
||||
local name BoneName;
|
||||
local vector LocOffset;
|
||||
local rotator RotOffset;
|
||||
|
||||
/* NO attachment for this item, early out */
|
||||
if(AttachmentClass == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* If attaching to a bone on the mesh, make sure to use relative values */
|
||||
if(StoryPickupBase != none )
|
||||
{
|
||||
LocOffset = StoryPickupBase.Attachment_Offset;
|
||||
RotOffset = StoryPickupBase.Attachment_Rotation;
|
||||
}
|
||||
|
||||
Instigator = P;
|
||||
if ( ThirdPersonActor == None )
|
||||
{
|
||||
ThirdPersonActor = Spawn(AttachmentClass,Owner);
|
||||
|
||||
if(ThirdPersonActor == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryAttachment(ThirdPersonActor).InitFor(self);
|
||||
}
|
||||
else
|
||||
ThirdPersonActor.NetUpdateTime = Level.TimeSeconds - 1;
|
||||
BoneName = InvAttachmentBone;
|
||||
if ( BoneName == '' )
|
||||
{
|
||||
// no attachment bone. Dont render in third person.
|
||||
ThirdPersonActor.SetBase(P);
|
||||
ThirdPersonActor.bHidden = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
P.AttachToBone(ThirdPersonActor,BoneName);
|
||||
|
||||
ThirdPersonActor.SetRelativeLocation(LocOffset);
|
||||
ThirdPersonActor.SetRelativeRotation(RotOffset);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function CopyPropertiesFrom(KF_StoryInventoryPickup OwningPickup)
|
||||
{
|
||||
StoryPickupBase = OwningPickup.StoryPickupBase;
|
||||
|
||||
MaxHeldCopies = OwningPickup.MaxHeldCopies;
|
||||
MovementSpeedModifier = OwningPickup.MovementSpeedModifier;
|
||||
AIThreatModifier = OwningPickup.AIThreatModifier;
|
||||
PickupSM = OwningPickup.StaticMesh;
|
||||
Weight = OwningPickup.Weight;
|
||||
CarriedMaterial = OwningPickup.CarriedMaterial ;
|
||||
GroundMaterial = OwningPickup.GroundMaterial;
|
||||
PrePivot = OwningPickup.PrePivot;
|
||||
AmbientGlow = OwningPickup.AmbientGlow;
|
||||
UV2Texture = OwningPickup.UV2Texture;
|
||||
bUseFirstPersonXRayEffect = OwningPickup.bUseFirstPersonXRayEffect;
|
||||
bRender1PMesh = OwningPickup.bRender1PMesh;
|
||||
ViewLocationOffset = OwningPickup.ViewLocationOffset;
|
||||
ViewRotationOffset = OwningPickup.ViewRotationOffset;
|
||||
Pickup_TossVelocity = OwningPickup.Pickup_TossVelocity;
|
||||
bDropFromCameraLoc = OwningPickup.bDropFromCameraLoc;
|
||||
ImpactDamType = OwningPickup.ImpactDamType;
|
||||
ImpactDamage = OwningPickup.ImpactDamage;
|
||||
|
||||
SetDrawScale(OwningPickup.DrawScale);
|
||||
SetStaticMesh(OwningPickup.StaticMesh);
|
||||
LinkMesh(OwningPickup.Mesh);
|
||||
SetDrawType(OwningPickup.DrawType);
|
||||
SetDrawScale3D(OwningPickup.DrawScale3D);
|
||||
SetRotation(OwningPickup.Rotation);
|
||||
SetCollisionSize(OwningPickup.CollisionRadius,OwningPickup.CollisionHeight);
|
||||
|
||||
if(StoryPickupBase != none)
|
||||
{
|
||||
JumpZModifier = StoryPickupBase.JumpZModifier;
|
||||
DroppedEvent = StoryPickupBase.DroppedEvent;
|
||||
CarriedEvents = StoryPickupBase.CarriedEvents;
|
||||
InvAttachmentBone = StoryPickupBase.Attachment_Bone;
|
||||
}
|
||||
|
||||
log("=================================================");
|
||||
log("Copy properties from : "@OwningPickup@" to - "@self);
|
||||
log("=================================================");
|
||||
}
|
||||
|
||||
|
||||
simulated function ClientItemThrown()
|
||||
{
|
||||
AmbientSound = None;
|
||||
Instigator.DeleteInventory(self);
|
||||
|
||||
if(Instigator.Weapon.IsA('Dummy_JoggingWeapon'))
|
||||
{
|
||||
Instigator.Controller.SwitchToBestWeapon();
|
||||
}
|
||||
}
|
||||
|
||||
function DropFrom(vector StartLocation)
|
||||
{
|
||||
local Pickup P;
|
||||
local Rotator VRot;
|
||||
|
||||
if( StoryPickupBase != none )
|
||||
{
|
||||
VRot = StoryPickupBase.Rotation;
|
||||
}
|
||||
|
||||
P = spawn(PickupClass,,,StartLocation,VRot);
|
||||
|
||||
if( P == none && Instigator != none )
|
||||
{
|
||||
// couldn't spawn using StartLocation, try Instigator's location and just drop it
|
||||
P = spawn(PickupClass,,,Instigator.Location,VRot);
|
||||
Velocity = vect(0,0,0);
|
||||
}
|
||||
|
||||
if ( P == None )
|
||||
{
|
||||
if( Instigator != none && Instigator.Health > 0 )
|
||||
{
|
||||
// couldn't spawn using Instigator's location, just hold on to it (do nothing)
|
||||
return;
|
||||
}
|
||||
|
||||
// Instigator can't hold on to it because he's dead, so freak out
|
||||
warn(self$" couldn't be dropped by instigator "$Instigator);
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
ClientItemThrown();
|
||||
|
||||
if ( Instigator != None )
|
||||
{
|
||||
if ( KFHumanPawn_Story( Instigator ) != none)
|
||||
{
|
||||
KFHumanPawn_Story( Instigator ).SetHasStoryItem( false );
|
||||
}
|
||||
|
||||
DetachFromPawn(Instigator);
|
||||
Instigator.DeleteInventory(self);
|
||||
}
|
||||
|
||||
UpdateHeldMaterial(Instigator,none);
|
||||
SetDefaultDisplayProperties();
|
||||
StopAnimating();
|
||||
GotoState('');
|
||||
|
||||
if(StoryPickupBase != none && KF_StoryInventoryPickup(P) != none)
|
||||
{
|
||||
StoryPickupBase.CopyPropertiesTo(KF_StoryInventoryPickup(P));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(KF_StoryInventoryPickup(P) != none)
|
||||
{
|
||||
KF_StoryInventoryPickup(P).MovementSpeedModifier = MovementSpeedModifier;
|
||||
}
|
||||
|
||||
P.Tag = tag; // make sure we copy the tag over to the new pickup .
|
||||
}
|
||||
|
||||
P.InitDroppedPickupFor(self);
|
||||
P.Velocity = Velocity;
|
||||
|
||||
Velocity = vect(0,0,0);
|
||||
Instigator = None;
|
||||
}
|
||||
|
||||
|
||||
simulated function float GetMovementModifierFor(Pawn InPawn)
|
||||
{
|
||||
return MovementSpeedmodifier;
|
||||
}
|
||||
|
||||
simulated function bool AllowHoldWeapon(Weapon InWeapon, optional bool SkipDummyWeap)
|
||||
{
|
||||
local int i;
|
||||
local bool Result;
|
||||
local array< class<Weapon> > AllowedWeaps,RestrictedWeaps;
|
||||
|
||||
if(InWeapon == none)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Hackity hack!*/
|
||||
if(!SkipDummyWeap &&
|
||||
InWeapon.IsA('Dummy_JoggingWeapon'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if(StoryPickupBase == none)
|
||||
{
|
||||
AllowedWeaps = AllowedWeapons;
|
||||
RestrictedWeaps = RestrictedWeapons;
|
||||
}
|
||||
else
|
||||
{
|
||||
AllowedWeaps = StoryPickupBase.Weapons_Allowed;
|
||||
RestrictedWeaps = StoryPickupBase.Weapons_Restricted;
|
||||
}
|
||||
|
||||
if(AllowedWeaps.length == 0)
|
||||
{
|
||||
Result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0 ; i < AllowedWeaps.length ; i ++)
|
||||
{
|
||||
if(ClassisChildOf(InWeapon.class,AllowedWeaps[i]))
|
||||
{
|
||||
Result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0 ; i < RestrictedWeaps.length ; i ++)
|
||||
{
|
||||
if(ClassisChildOf(InWeapon.class,RestrictedWeaps[i]))
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// log("does"@self@" allow the use of :"@InWeapon@" ? :"@Result);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
simulated function bool IsThrowable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ImpactDamType = class 'Engine.Crushed'
|
||||
ImpactDamage = 0
|
||||
Pickup_TossVelocity = 250
|
||||
|
||||
BobDamping=5.000000
|
||||
PlayerViewOffset = (X=25,Y=0,Z=-20)
|
||||
JumpZModifier = 1.f
|
||||
AIThreatModifier = 1.f
|
||||
MovementSpeedModifier = 1.f
|
||||
PickupClass = class 'KF_StoryInventoryPickup'
|
||||
AttachmentClass = class 'StoryInventoryAttachment'
|
||||
InvAttachmentBone = "CHR_LArmForeArm"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
394
kf_sources/KFStoryGame/Classes/KF_StoryInventoryPickup.uc
Normal file
394
kf_sources/KFStoryGame/Classes/KF_StoryInventoryPickup.uc
Normal file
|
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryInventoryPickup
|
||||
--------------------------------------------------------------
|
||||
|
||||
Base class for Objective-driven inventory items which players can
|
||||
hold on their pawns.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_StoryInventoryPickup extends Pickup
|
||||
notplaceable;
|
||||
|
||||
/* Number of items of this class which can be held by a pawn at once */
|
||||
var int MaxHeldCopies;
|
||||
|
||||
var Material CarriedMaterial;
|
||||
|
||||
var Material GroundMaterial;
|
||||
|
||||
var float MovementSpeedModifier;
|
||||
|
||||
var float Pickup_TossVelocity;
|
||||
|
||||
var class<DamageType> ImpactDamType;
|
||||
|
||||
var int ImpactDamage;
|
||||
|
||||
var bool bDropFromCameraLoc;
|
||||
|
||||
var string DroppedMessage; // Human readable description when dropped.
|
||||
|
||||
var string UseMeMessage;
|
||||
|
||||
var bool bRender1PMesh;
|
||||
|
||||
var Rotator PlacedRotation;
|
||||
|
||||
var float LastUseMeMsgTime;
|
||||
|
||||
var bool bRenderIconThroughWalls;
|
||||
|
||||
var rotator ViewRotationOffset;
|
||||
|
||||
var vector ViewLocationOffset;
|
||||
|
||||
/* When holding this item, display it with an 'X-Ray' shader in first person */
|
||||
var bool bUseFirstPersonXRayEffect;
|
||||
|
||||
/* Sound this pickup makes when it falls to the floor */
|
||||
var Sound DroppedSound;
|
||||
|
||||
/* Number of inventory blocks this item takes up when carried */
|
||||
var int Weight;
|
||||
|
||||
/* Changes the amount of interest ZEDs will show in the player holding this item */
|
||||
var float AIThreatModifier;
|
||||
|
||||
var KF_PlaceableStoryPickup StoryPickupBase;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if (Role== Role_Authority)
|
||||
GroundMaterial,bRenderIconThroughWalls;
|
||||
}
|
||||
|
||||
|
||||
static function string GetLocalString(
|
||||
optional int Switch,
|
||||
optional PlayerReplicationInfo RelatedPRI_1,
|
||||
optional PlayerReplicationInfo RelatedPRI_2
|
||||
)
|
||||
{
|
||||
if(Switch == 1)
|
||||
{
|
||||
return default.DroppedMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
return default.PickupMessage;
|
||||
}
|
||||
}
|
||||
|
||||
state FallingPickup
|
||||
{
|
||||
// Story Inventory pickups can't be grabbed by walking over them.
|
||||
function Touch( actor Other )
|
||||
{
|
||||
if(ImpactDamage > 0 && Other != Instigator)
|
||||
{
|
||||
Other.TakeDamage(ImpactDamage,Instigator,Other.Location,Velocity,ImpactDamType);
|
||||
}
|
||||
}
|
||||
|
||||
event Landed( vector HitNormal )
|
||||
{
|
||||
Global.Landed(HitNormal);
|
||||
if(DroppedSound != none)
|
||||
{
|
||||
PlaySound(DroppedSound,,2.f,false,SoundRadius,SoundPitch,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto state Pickup
|
||||
{
|
||||
function Timer()
|
||||
{
|
||||
}
|
||||
|
||||
// Story Inventory pickups can't be grabbed by walking over them.
|
||||
function Touch( actor Other )
|
||||
{
|
||||
if(!ValidTouch(Other))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(Pawn(Other) != none && PlayerController(Pawn(Other).Controller) != none && Level.TimeSeconds - LastUseMeMsgTime > 4.f)
|
||||
{
|
||||
LastUseMeMsgTime = Level.TimeSeconds;
|
||||
PlayerController(Pawn(Other).Controller).ClientMessage(UseMeMessage, 'KFCriticalEvent');
|
||||
}
|
||||
|
||||
/* Have KFBots auto pickup stuff for testing purposes*/
|
||||
if(Pawn(Other) != none && KFInvasionBot(Pawn(Other).Controller) != none)
|
||||
{
|
||||
UsedBy(Pawn(Other));
|
||||
}
|
||||
}
|
||||
|
||||
/* ValidTouch()
|
||||
Validate touch (if valid return true to let other pick me up and trigger event).
|
||||
*/
|
||||
function bool ValidTouch( actor Other )
|
||||
{
|
||||
// make sure its a live player
|
||||
if ( (Pawn(Other) == None) || !Pawn(Other).bCanPickupInventory || (Pawn(Other).DrivenVehicle == None && Pawn(Other).Controller == None) )
|
||||
return false;
|
||||
|
||||
/* Too much weight .. ? */
|
||||
if (KFHumanPawn(Other) != none && !KFHumanPawn(Other).CanCarry(Weight))
|
||||
{
|
||||
PlayerController(Pawn(Other).Controller).ReceiveLocalizedMessage(Class'KFMainMessages', 4);
|
||||
return false;
|
||||
}
|
||||
/* Too many held copies ? */
|
||||
if(IsHoldingTooManyCopies(Pawn(Other)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure not touching through wall
|
||||
if ( !FastTrace(Other.Location, Location) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
event UsedBy( Pawn user)
|
||||
{
|
||||
local Inventory Copy;
|
||||
local KF_StoryInventoryPickup P,Closest;
|
||||
local float Dist,ClosestDist;
|
||||
|
||||
/* Only grab one inventory pickup at a time */
|
||||
foreach User.TouchingActors(class 'KF_StoryInventoryPickup', P)
|
||||
{
|
||||
Dist = VSizeSquared(P.Location - Location);
|
||||
if(ClosestDist == 0 || Dist < ClosestDist)
|
||||
{
|
||||
ClosestDist = Dist;
|
||||
Closest = P;
|
||||
}
|
||||
}
|
||||
|
||||
// If used by a player pawn, let him pick this up.
|
||||
if( Closest == self && ValidTouch(user) )
|
||||
{
|
||||
Copy = SpawnCopy(user);
|
||||
AnnouncePickup(user);
|
||||
SetRespawn();
|
||||
if ( Copy != None )
|
||||
Copy.PickupFunction(user);
|
||||
|
||||
TriggerEvent(Event, self, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function AnnouncePickup( Pawn Receiver )
|
||||
{
|
||||
BroadCastPickupEvent(Receiver,1);
|
||||
PlaySound( PickupSound,SLOT_Interact );
|
||||
}
|
||||
|
||||
function AnnounceDropped( Pawn Dropper)
|
||||
{
|
||||
BroadCastPickupEvent(Dropper,2);
|
||||
}
|
||||
|
||||
function BroadCastPickupEvent( Pawn Receiver , int Switch)
|
||||
{
|
||||
local Controller C;
|
||||
local PlayerController PC;
|
||||
|
||||
for ( C=Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
PC = PlayerController(C);
|
||||
if(PC != none)
|
||||
{
|
||||
PC.ReceiveLocalizedMessage(MessageClass,Switch,Receiver.PlayerReplicationInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simulated function bool IsHoldingTooManyCopies(pawn InPawn)
|
||||
{
|
||||
local Inventory Inv;
|
||||
local int NumHeld;
|
||||
|
||||
if(MaxHeldCopies <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for( inv=InPawn.Inventory; inv!=None; inv=inv.Inventory )
|
||||
{
|
||||
if(Inv.class == InventoryType)
|
||||
{
|
||||
NumHeld ++;
|
||||
}
|
||||
}
|
||||
|
||||
return (NumHeld + 1) > MaxHeldCopies;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Draw floating icons overtop of pickups, on request */
|
||||
simulated event RenderOverlays( canvas Canvas )
|
||||
{
|
||||
local float Opacity;
|
||||
local float IconSize;
|
||||
local float XCentre,YCentre;
|
||||
local vector ScreenPos;
|
||||
local Material RenderMat;
|
||||
local vector CameraLocation;
|
||||
local rotator CameraRotation;
|
||||
local float Dist;
|
||||
|
||||
Super.RenderOverlays(Canvas);
|
||||
|
||||
if(GroundMaterial == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Canvas.GetCameraLocation(CameraLocation, CameraRotation);
|
||||
|
||||
/* fading jazz from PlayerBeacon code */
|
||||
|
||||
Dist = vsize(CameraLocation-Location);
|
||||
Dist -= class 'HUDKillingFloor'.default.HealthBarFullVisDist;
|
||||
Dist = FClamp(Dist, 0, class 'HUDKillingFloor'.default.HealthBarCutoffDist-class 'HUDKillingFloor'.default.HealthBarFullVisDist);
|
||||
Dist = Dist / (class 'HUDKillingFloor'.default.HealthBarCutoffDist- class 'HUDKillingFloor'.default.HealthBarFullVisDist);
|
||||
Opacity = Max(byte((1.f - Dist) * 255.f),100.f);
|
||||
|
||||
if(!bRenderIconThroughWalls && !FastTrace(Location,CameraLocation))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RenderMat = GroundMaterial ;
|
||||
IconSize = GroundMaterial.MaterialUSize();
|
||||
|
||||
ScreenPos = Canvas.WorldToScreen(Location + CollisionHeight * Vect(0,0,1));
|
||||
|
||||
XCentre = ScreenPos.X;
|
||||
YCentre = ScreenPos.Y;
|
||||
|
||||
/* Dont render stuff behind the camera */
|
||||
if ( (Normal(Location - CameraLocation) dot vector(CameraRotation)) < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Canvas.DrawColor.R = 255;
|
||||
Canvas.DrawColor.G = 255;
|
||||
Canvas.DrawColor.B = 255;
|
||||
Canvas.DrawColor.A = Opacity;
|
||||
|
||||
Canvas.SetPos(XCentre - (0.5 * IconSize) + 1.0, YCentre - (0.5 * IconSize) + 1.0);
|
||||
Canvas.DrawTileScaled(RenderMat, IconSize/ RenderMat.MaterialVSize() ,IconSize/ RenderMat.MaterialVSize() );
|
||||
}
|
||||
|
||||
function InitDroppedPickupFor(Inventory Inv)
|
||||
{
|
||||
SetPhysics(PHYS_Falling);
|
||||
GotoState('FallingPickup');
|
||||
Inventory = Inv;
|
||||
bAlwaysRelevant = false;
|
||||
bOnlyReplicateHidden = false;
|
||||
bUpdateSimulatedPosition = true;
|
||||
bDropped = true;
|
||||
bIgnoreEncroachers = false; // handles case of dropping stuff on lifts etc
|
||||
NetUpdateFrequency = 8;
|
||||
// Inv.Instigator.HandlePickup(self);
|
||||
Instigator = Inv.Instigator;
|
||||
BroadCastPickupEvent(Inv.Instigator,2);
|
||||
}
|
||||
|
||||
/* Create an Inventory Item for this Pickup */
|
||||
|
||||
function inventory SpawnCopy( pawn Other )
|
||||
{
|
||||
local Inventory Copy;
|
||||
local KF_StoryInventoryItem StoryInv;
|
||||
|
||||
if ( Inventory != None )
|
||||
{
|
||||
Copy = Inventory;
|
||||
Inventory = None;
|
||||
}
|
||||
else
|
||||
{
|
||||
Copy = spawn(InventoryType,Other,,,rot(0,0,0));
|
||||
}
|
||||
|
||||
Copy.Tag = tag;
|
||||
|
||||
|
||||
StoryInv = KF_StoryInventoryItem(Copy);
|
||||
if(StoryInv != none)
|
||||
{
|
||||
StoryInv.CopyPropertiesFrom(self);
|
||||
}
|
||||
|
||||
Copy.GiveTo( Other, self );
|
||||
|
||||
return Copy;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ImpactDamType = class 'Engine.Crushed'
|
||||
ImpactDamage = 0
|
||||
Pickup_TossVelocity = 250
|
||||
|
||||
bRenderIconThroughWalls = true
|
||||
bRender1PMesh = true
|
||||
|
||||
bOrientOnSlope=false
|
||||
|
||||
bCollideActors = true
|
||||
bIgnoreEncroachers = false
|
||||
|
||||
MovementSpeedModifier = 1.f
|
||||
AIThreatModifier = 1.f
|
||||
|
||||
DrawType = DT_StaticMesh
|
||||
Physics = PHYS_Falling
|
||||
StaticMesh = StaticMesh 'DetailSM.Crates.WoodBox_B'
|
||||
PrePivot=(X=0,Y=0,Z=10)
|
||||
DrawScale = 1
|
||||
|
||||
CollisionHeight = 10
|
||||
CollisionRadius = 30
|
||||
|
||||
InventoryType = class 'KF_StoryInventoryItem'
|
||||
UseMeMessage = "Press USE key to Pick up"
|
||||
MessageClass=class'PickupMessagePlus'
|
||||
DroppedMessage = "You dropped the gold bars."
|
||||
|
||||
bOnlyReplicateHidden = false
|
||||
bNetinitialRotation =true
|
||||
bFixedRotationDir = false
|
||||
|
||||
NetUpdateFrequency = 8
|
||||
|
||||
DroppedSound = Sound'Inf_Player.RagdollImpacts.BodyImpact'
|
||||
PickupSound = Sound 'KF_AxeSnd.Axe_Select'
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
564
kf_sources/KFStoryGame/Classes/KF_StoryNPC.uc
Normal file
564
kf_sources/KFStoryGame/Classes/KF_StoryNPC.uc
Normal file
|
|
@ -0,0 +1,564 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
LD Placeable NPC actor. Can be controlled by AI Scripts
|
||||
(for non-combat behaviour). Or with the KF_StoryNPC_AI controller
|
||||
for simple combat AI.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_StoryNPC extends KFHumanPawn
|
||||
placeable
|
||||
hidecategories(DeRes,Bob,Blur,UDamage);
|
||||
|
||||
var () localized array<string> NPCDialogue;
|
||||
|
||||
var () localized string NPCName;
|
||||
|
||||
var KF_DialogueSpot DialogueTrigger;
|
||||
|
||||
var () bool bRunning;
|
||||
|
||||
var name RunningAnims[8];
|
||||
|
||||
var () float BaseGroundSpeed;
|
||||
|
||||
var () float RespawnTime;
|
||||
|
||||
var () bool bStartActive;
|
||||
|
||||
var () bool bIndestructible;
|
||||
|
||||
var (AI) int TeamIndex;
|
||||
|
||||
var (AI) bool bFireAtWill;
|
||||
|
||||
var (AI) float BaseAIThreatRating;
|
||||
|
||||
var (AI) array< class <Pawn> > OnlyThreateningTo,NotThreateningTo;
|
||||
|
||||
var (AI) bool bNoThreatToZEDs;
|
||||
|
||||
var bool bShotAnim;
|
||||
|
||||
var () bool bHasInfiniteAmmo;
|
||||
|
||||
var bool bInitialFireAtWill;
|
||||
|
||||
var () bool bDropInventoryOnDeath;
|
||||
|
||||
/* If true, this pawn is marked Hidden while inactive. */
|
||||
var (Display) bool bOnlyVisibleWhenActive;
|
||||
|
||||
/* Initial location this NPC was placed at by the L.D */
|
||||
var vector PlacedLoc;
|
||||
|
||||
var rotator PlacedRot;
|
||||
|
||||
/* Modifier to apply to incoming damage from friendly pawns */
|
||||
var() float FriendlyFireDamageScale;
|
||||
|
||||
var() bool bShowHealthBar;
|
||||
|
||||
var(Movement) bool bUseDefaultPhysics;
|
||||
|
||||
var() float NPCHealth;
|
||||
|
||||
var() float StartingHealthPct;
|
||||
|
||||
var() bool bDamageable;
|
||||
|
||||
var bool bActive;
|
||||
|
||||
var bool bInitialActive;
|
||||
|
||||
/* Event to fire off when this NPC becomes 'Active' */
|
||||
var(Events) name ActivationEvent,DeActivationEvent,HealedEvent;
|
||||
|
||||
var(Pawn) bool bUseHitPoints;
|
||||
|
||||
enum ENPCTriggerAction
|
||||
{
|
||||
TA_ToggleHoldFire,
|
||||
TA_CommitSuicide,
|
||||
TA_ToggleActive,
|
||||
};
|
||||
|
||||
|
||||
var () ENPCTriggerAction TriggerAction;
|
||||
|
||||
replication
|
||||
{
|
||||
reliable if(Role == Role_Authority)
|
||||
bActive;
|
||||
}
|
||||
|
||||
/* Stub. The objective just changed. Called from KFStoryGameinfo.SetActiveObjective() */
|
||||
function OnObjectiveChanged(name OldObjectiveName, name NewObjectiveName){}
|
||||
|
||||
function SetMovemetPhysics()
|
||||
{
|
||||
if(!bUseDefaultPhysics)
|
||||
{
|
||||
Super.SetMovementPhysics();
|
||||
}
|
||||
}
|
||||
|
||||
function bool HealDamage(int Amount, Controller Healer, class<DamageType> DamageType)
|
||||
{
|
||||
Health = Min(Health + Amount, HealthMax);
|
||||
return true;
|
||||
}
|
||||
|
||||
function ProcessLocationalDamage(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class<DamageType> damageType, array<int> PointsHit )
|
||||
{
|
||||
if(!bUseHitPoints)
|
||||
{
|
||||
TakeDamage(Damage,instigatedBy,HitLocation,Momentum,damageType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Super.ProcessLocationalDamage(Damage,InstigatedBy,HitLocation,Momentum,DamageType,PointsHit);
|
||||
}
|
||||
}
|
||||
|
||||
function SaveHealthState(){}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
bFireAtWill = bInitialFireAtWill ;
|
||||
SetActive(bInitialActive);
|
||||
ResurrectNPC();
|
||||
}
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
local AIScript A;
|
||||
|
||||
Super.PostbeginPlay();
|
||||
|
||||
SpawnDialogueTrigger();
|
||||
|
||||
bInitialFireAtWill = bFireAtWill;
|
||||
|
||||
if(bStartActive)
|
||||
{
|
||||
SetActive(true);
|
||||
}
|
||||
|
||||
if(bOnlyVisibleWhenActive)
|
||||
{
|
||||
UpdateVisibility(bActive);
|
||||
}
|
||||
|
||||
bInitialActive = bActive;
|
||||
|
||||
PlacedLoc = Location;
|
||||
PlacedRot = Rotation;
|
||||
GroundSpeed = BaseGroundSpeed;
|
||||
MenuName = NPCName;
|
||||
Health = NPCHealth * StartingHealthPct;
|
||||
HealthMax = NPCHealth;
|
||||
|
||||
// automatically add controller to pawns which were placed in level
|
||||
// NOTE: pawns spawned during gameplay are not automatically possessed by a controller
|
||||
if ( (Health > 0) && !bDontPossess )
|
||||
{
|
||||
// check if I have an AI Script
|
||||
if ( AIScriptTag != '' )
|
||||
{
|
||||
ForEach AllActors(class'AIScript',A,AIScriptTag)
|
||||
break;
|
||||
// let the AIScript spawn and init my controller
|
||||
if ( A != None )
|
||||
{
|
||||
A.SpawnControllerFor(self);
|
||||
if ( Controller != None )
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( (ControllerClass != None) && (Controller == None) )
|
||||
Controller = spawn(ControllerClass);
|
||||
if ( Controller != None )
|
||||
{
|
||||
Controller.Possess(self);
|
||||
AIController(Controller).Skill += SkillModifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function ResurrectNPC()
|
||||
{
|
||||
if(Health < NPCHealth)
|
||||
{
|
||||
Health = NPCHealth * StartingHealthPct;
|
||||
HealthMax = NPCHealth;
|
||||
SetCollision(true,true);
|
||||
bHidden = false;
|
||||
RepositionNPC();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function RepositionNPC()
|
||||
{
|
||||
if(bMovable)
|
||||
{
|
||||
SetRotation(PlacedRot);
|
||||
SetLocation(PlacedLoc);
|
||||
}
|
||||
}
|
||||
|
||||
function SpawnDialogueTrigger()
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(DialogueTrigger == none && NPCDialogue.length > 0)
|
||||
{
|
||||
DialogueTrigger = Spawn(class 'KF_DialogueSpot');
|
||||
DialogueTrigger.bTouchTriggered = true;
|
||||
DialogueTrigger.bRandomize = true;
|
||||
DialogueTrigger.bHardAttach = true;
|
||||
DialogueTrigger.SetBase(self);
|
||||
DialogueTrigger.SetCollisionSize(CollisionRadius * 1.5,CollisionHeight) ;
|
||||
|
||||
for(i = 0 ; i < NPCDialogue.length ; i ++)
|
||||
{
|
||||
DialogueTrigger.Dialogues.length = i + 1;
|
||||
DialogueTrigger.Dialogues[i].Display.Dialogue_text = NPCDialogue[i];
|
||||
DialogueTrigger.Dialogues[i].Display.Dialogue_header = NPCName;
|
||||
DialogueTrigger.Dialogues[i].BroadcastScope = InstigatorOnly;
|
||||
DialogueTrigger.Dialogues[i].VoiceOver.SourceActor = self;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Doing this here instead of in Gameinfo.ReduceDamage() because of how hilariously hacked up KFGameType's implementation
|
||||
of that function is ... */
|
||||
|
||||
simulated function TakeDamage(int Damage,pawn instigatedBy, Vector HitLocation, vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
||||
{
|
||||
local int ReducedDamage;
|
||||
|
||||
/* log("=============================================================",'Story_Debug');
|
||||
log(self@"Took Damage : "@Damage@" from : "@instigatedBy@" Am I damageable ? : "@bDamageable@" Current Health : "@Health,'Story_Debug');
|
||||
*/
|
||||
|
||||
if(!bDamageable || Health <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReducedDamage = Damage;
|
||||
|
||||
// friendly fire ... scale down the damage
|
||||
if(/*instigatedBy.Controller.GetTeamNum() == Controller.GetTeamNum()*/
|
||||
PlayerController(instigatedBy.Controller) != none) // Yeah looks like this guy's never actually getting assigned a correct team.
|
||||
{
|
||||
ReducedDamage *= FriendlyFireDamageScale;
|
||||
}
|
||||
|
||||
Super.TakeDamage(ReducedDamage,InstigatedBy,HitLocation,Momentum,damageType,HitIndex);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function bool GiveHealth(int HealAmount, int HealMax)
|
||||
{
|
||||
local bool bHealed;
|
||||
|
||||
bHealed = Super.GiveHealth(HealAmount,HealMax);
|
||||
|
||||
if(HealedEvent != '' && HealAmount > 0 && bHealed)
|
||||
{
|
||||
TriggerEvent(HealedEvent,self,Instigator);
|
||||
}
|
||||
|
||||
|
||||
return bHealed;
|
||||
}
|
||||
|
||||
/*
|
||||
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
||||
{
|
||||
if(!bPlayedDeath && !bIndestructible)
|
||||
{
|
||||
SpawnDummyCorpse(Killer,damageType,HitLocation);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc)
|
||||
{
|
||||
Super(xPawn).PlayDying(DamageType,HitLoc);
|
||||
}*/
|
||||
|
||||
simulated function SpawnDummyCorpse(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
||||
{
|
||||
local KFPawn DummyCorpse;
|
||||
local int i, EquipLength;
|
||||
|
||||
SetCollision(false,false);
|
||||
bHidden = true;
|
||||
|
||||
DummyCorpse = Spawn(class 'KFHumanPawn',,,Location,Rotation);
|
||||
if(DummyCorpse != none)
|
||||
{
|
||||
DummyCorpse.LinkMesh(Mesh);
|
||||
DummyCorpse.tag = tag;
|
||||
DummyCorpse.Event = Event;
|
||||
|
||||
if(bDropInventoryOnDeath)
|
||||
{
|
||||
EquipLength = arraycount(RequiredEquipment);
|
||||
for(i = 0 ; i < EquipLength ; i ++)
|
||||
{
|
||||
DummyCorpse.RequiredEquipment[i] = RequiredEquipment[i] ;
|
||||
}
|
||||
|
||||
DummyCorpse.AddDefaultInventory();
|
||||
}
|
||||
|
||||
DummyCorpse.Died(Killer,damageType,HitLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Trigger( Actor Other, Pawn EventInstigator )
|
||||
{
|
||||
switch(TriggerAction)
|
||||
{
|
||||
case TA_CommitSuicide : Died(Controller,class 'Suicided', Location) ; break;
|
||||
case TA_ToggleHoldFire : bFireAtWill = !bFireAtWill; break;
|
||||
case TA_ToggleActive : SetActive(!bActive); break;
|
||||
}
|
||||
}
|
||||
|
||||
function UpdateVisibility(bool On)
|
||||
{
|
||||
if(bOnlyVisibleWhenActive)
|
||||
{
|
||||
bHidden = !On;
|
||||
SetCollision(!bHidden,!bHidden);
|
||||
}
|
||||
}
|
||||
|
||||
/* turns this NPC on / off
|
||||
ie. Makes it damageable and decides whether AI ignores it
|
||||
|
||||
Network : Server */
|
||||
|
||||
function SetActive(bool On)
|
||||
{
|
||||
if(Role < Role_Authority)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateVisibility(On);
|
||||
|
||||
bActive = On;
|
||||
bDamageable = bActive;
|
||||
log(self@" is now bActive : "@On,'Story_Debug');
|
||||
|
||||
if(On && ActivationEvent != '')
|
||||
{
|
||||
TriggerEvent(ActivationEvent,self,self);
|
||||
}
|
||||
else
|
||||
if(!On && DeActivationEvent != '')
|
||||
{
|
||||
TriggerEvent(DeActivationEvent,self,self);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function int GetTeamNum()
|
||||
{
|
||||
return TeamIndex;
|
||||
}
|
||||
|
||||
/* === AI functions =====================================*/
|
||||
|
||||
function float AssessThreatTo(KFMonsterController Monster, optional bool CheckDistance)
|
||||
{
|
||||
if(bNoThreatToZEDs ||
|
||||
TeamIndex == 255 ||
|
||||
Health <= 0 ||
|
||||
!bActive ||
|
||||
!bDamageable ||
|
||||
(!IsThreateningTo(Monster.Pawn)) )
|
||||
{
|
||||
return -1.f;
|
||||
}
|
||||
|
||||
return Super.AssessThreatTo(Monster,CheckDistance) + BaseAIThreatRating ;
|
||||
}
|
||||
|
||||
/* Returns true if the supplied Monster considers this NPC a threat (and is prepared to attack it) */
|
||||
function bool IsThreateningTo( Pawn Monster)
|
||||
{
|
||||
local int i;
|
||||
local bool Result;
|
||||
|
||||
if(Monster == none)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = true;
|
||||
|
||||
for(i = 0 ; i < NotThreateningTo.length ; i ++)
|
||||
{
|
||||
if(ClassisChildOf(Monster.class,NotThreateningTo[i]))
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0 ; i < OnlyThreateningTo.length ; i ++)
|
||||
{
|
||||
Result = false;
|
||||
if(ClassisChildOf(Monster.class,OnlyThreateningTo[i]))
|
||||
{
|
||||
Result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
function bool IsPacifist()
|
||||
{
|
||||
local Inventory Inv;
|
||||
local int Count;
|
||||
local Weapon Weap;
|
||||
local bool bUsingLethalGear;
|
||||
|
||||
for( Inv=Inventory; Inv!=None && Count < 1000; Inv=Inv.Inventory )
|
||||
{
|
||||
Weap = Weapon(Inv);
|
||||
|
||||
bUsingLethalGear = Weap != none && (Weap.bMeleeWeapon || Weap.HasAmmo()) ;
|
||||
if(bUsingLethalGear && bFireAtWill)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Count++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
simulated event PostRender2D(Canvas C, float ScreenLocX, float ScreenLocY) // called if bScriptPostRender is true, overrides native team beacon drawing code
|
||||
{
|
||||
local PlayerController PC;
|
||||
local float Opacity;
|
||||
// local float Dist;
|
||||
local HUDKillingFloor KFHUD;
|
||||
local vector CameraLocation,CamDir;
|
||||
local rotator CameraRotation;
|
||||
|
||||
if(!bShowHealthBar ||
|
||||
!bActive ||
|
||||
GetStateName() == 'Dying')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PC = Level.GetLocalPlayerController();
|
||||
|
||||
if ( PC != None )
|
||||
{
|
||||
KFHUD = HUDKillingFloor(PC.myHUD);
|
||||
if(KFHUD != none)
|
||||
{
|
||||
C.GetCameraLocation(CameraLocation, CameraRotation);
|
||||
CamDir = vector(CameraRotation);
|
||||
|
||||
/* Rendering behind us... */
|
||||
if ( (Normal(Location - CameraLocation) dot CamDir) < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Opacity = FClamp(1.f - (VSize(PC.CalcViewLocation - Location) / 3000.f),0.25f,1.f) ;
|
||||
KFHUD.DrawKFBar(C,ScreenLocX,ScreenLocY,Health/HealthMax,Byte(Opacity * 255.f),false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function RosterEntry GetPlacedRoster()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
function string GetPlayerName()
|
||||
{
|
||||
return NPCName;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
/* AccelRate=1000.0
|
||||
AirControl=+0.15
|
||||
GroundSpeed=200.0
|
||||
WaterSpeed=200.000000
|
||||
AirSpeed=230.000000
|
||||
JumpZ=325.000000
|
||||
MaxFallSpeed=600.000000
|
||||
BaseEyeHeight=44.0
|
||||
EyeHeight=44.0
|
||||
CrouchHeight=34.000000
|
||||
CollisionHeight=50.000000
|
||||
|
||||
Mesh=SkeletalMesh'KF_Soldier_Trip.Punk_Harold'
|
||||
|
||||
MovementAnims(0) ="WalkF_HuskGun"
|
||||
MovementAnims(1) ="WalkB_HuskGun"
|
||||
MovementAnims(2) ="WalkL_HuskGun"
|
||||
MovementAnims(3) ="WalkR_HuskGun"
|
||||
|
||||
|
||||
RunningAnims(0) = "JogF_Bullpup"
|
||||
RunningAnims(1) = "JogB_Bullpup"
|
||||
RunningAnims(2) = "JogL_Bullpup"
|
||||
RunningAnims(3) = "JogR_Bullpup"
|
||||
|
||||
|
||||
IdleWeaponAnim="Idle_Knife"
|
||||
IdleRestAnim="Idle_Knife"
|
||||
|
||||
TurnLeftAnim="TurnL"
|
||||
TurnRightAnim="TurnR"
|
||||
*/
|
||||
|
||||
NPCName ="An NPC"
|
||||
|
||||
|
||||
bNoDelete = true
|
||||
bFireAtWill = true
|
||||
ControllerClass = class 'KF_StoryNPC_AI'
|
||||
|
||||
TeamIndex = 0
|
||||
NPCHealth = 100
|
||||
FriendlyFireDamageScale = 1.f
|
||||
|
||||
bDropInventoryOnDeath = true
|
||||
|
||||
bStartActive = true
|
||||
bDamageable = true
|
||||
StartingHealthPct = 1.f
|
||||
|
||||
bAlwaysRelevant = true
|
||||
bUseHitPoints = true
|
||||
|
||||
TriggerAction = TA_ToggleActive
|
||||
}
|
||||
48
kf_sources/KFStoryGame/Classes/KF_StoryNPC_AI.uc
Normal file
48
kf_sources/KFStoryGame/Classes/KF_StoryNPC_AI.uc
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
class KF_StoryNPC_AI extends ScriptedController;
|
||||
|
||||
var KF_StoryNPC StoryPawn;
|
||||
|
||||
simulated function int GetTeamNum()
|
||||
{
|
||||
if(StoryPawn == none)
|
||||
{
|
||||
return 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
return StoryPawn.TeamIndex;
|
||||
}
|
||||
}
|
||||
|
||||
function bool SameTeamAs(Controller C)
|
||||
{
|
||||
if(KFMonsterController(C) != none)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function Possess(Pawn aPawn)
|
||||
{
|
||||
Super.Possess(aPawn);
|
||||
|
||||
StoryPawn = KF_StoryNPC(Pawn);
|
||||
if(StoryPawn != none)
|
||||
{
|
||||
bIsPlayer = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
FovAngle=+00085.000000
|
||||
bCanOpenDoors=true
|
||||
bCanDoSpecial=true
|
||||
bIsPlayer=false
|
||||
bStasis=false
|
||||
RotationRate=(Pitch=3072,Yaw=30000,Roll=2048)
|
||||
RemoteRole=ROLE_None
|
||||
}
|
||||
50
kf_sources/KFStoryGame/Classes/KF_StoryNPC_Spawnable.uc
Normal file
50
kf_sources/KFStoryGame/Classes/KF_StoryNPC_Spawnable.uc
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
|
||||
a runtime-spawnable version of the KF_StoryNPC
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_StoryNPC_Spawnable extends KF_StoryNPC
|
||||
notplaceable;
|
||||
|
||||
function Reset()
|
||||
{
|
||||
bFireAtWill = bInitialFireAtWill ;
|
||||
SetActive(bInitialActive);
|
||||
}
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
/* need to manually spawn controllers for non editor-placed pawns */
|
||||
Super.PostBeginPlay();
|
||||
|
||||
if(Controller == none)
|
||||
{
|
||||
Controller = Spawn(ControllerClass);
|
||||
Controller.Possess(self);
|
||||
}
|
||||
|
||||
Skins.length = 0;
|
||||
SetMovementPhysics();
|
||||
}
|
||||
|
||||
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
||||
{
|
||||
if(Controller != none)
|
||||
{
|
||||
// so that the controller will get garbage collected */
|
||||
Controller.bIsPlayer = false;
|
||||
}
|
||||
|
||||
/* skip the phoney corpse stuff in the superclass and just do a normal death */
|
||||
Super(KFPawn).Died(Killer,damageType,HitLocation);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bNoDelete = false
|
||||
}
|
||||
107
kf_sources/KFStoryGame/Classes/KF_StoryNPC_Static.uc
Normal file
107
kf_sources/KFStoryGame/Classes/KF_StoryNPC_Static.uc
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryNPC_Static
|
||||
--------------------------------------------------------------
|
||||
|
||||
StaticMesh NPC that can take damage.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_StoryNPC_Static extends KF_StoryNPC;
|
||||
|
||||
var bool bCheckPointed;
|
||||
|
||||
var float SavedHealth;
|
||||
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
Super.PostbeginPlay();
|
||||
|
||||
if(!bUseHitPoints)
|
||||
{
|
||||
Hitpoints.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function ResurrectNPC(){}
|
||||
|
||||
|
||||
function SaveHealthState()
|
||||
{
|
||||
bCheckPointed = true;
|
||||
SavedHealth = Health;
|
||||
}
|
||||
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
if(bCheckPointed)
|
||||
{
|
||||
Health = SavedHealth;
|
||||
}
|
||||
}
|
||||
|
||||
event EncroachedBy( actor Other ){}
|
||||
|
||||
|
||||
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
||||
{
|
||||
local Controller PC;
|
||||
|
||||
SpawnGibs(rotation, 1);
|
||||
|
||||
|
||||
/* Necessary because this pawn never dies .. we dont want AI Controllers getting stuck in infinite loops trying to attack it */
|
||||
for ( PC=Level.ControllerList; PC!=None; PC=PC.NextController )
|
||||
{
|
||||
if(PC.Enemy == self)
|
||||
{
|
||||
PC.Enemy = none;
|
||||
}
|
||||
}
|
||||
|
||||
if(bIndestructible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BaseAIThreatRating = -1.f;
|
||||
}
|
||||
|
||||
// Don't spawn any inventory for a static NPC
|
||||
function AddDefaultInventory(){}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
RespawnTime 1.f
|
||||
|
||||
bUseHitPoints = false
|
||||
bMovable = false
|
||||
bStatic = false // <--- I really wanna set this to true but if I do ... this actor can't receive any events.
|
||||
bUseDefaultPhysics = true
|
||||
bStaticLighting = true
|
||||
bShadowCast=True
|
||||
bPlayerShadows=false
|
||||
bActorShadows = false
|
||||
bDramaticLighting=false
|
||||
bPathColliding = true
|
||||
bUseCylinderCollision = false
|
||||
bCanPickupInventory = false
|
||||
|
||||
NetUpdateFrequency = 5.f
|
||||
|
||||
bIndestructible = true
|
||||
bCanJump = false
|
||||
bCanBeHealed = false
|
||||
|
||||
Physics = PHYS_NONE
|
||||
DrawType = DT_StaticMesh
|
||||
StaticMesh = StaticMesh'Waterworks_SM.pipe01_03'
|
||||
|
||||
ControllerClass = class 'AIController'
|
||||
}
|
||||
1579
kf_sources/KFStoryGame/Classes/KF_StoryObjective.uc
Normal file
1579
kf_sources/KFStoryGame/Classes/KF_StoryObjective.uc
Normal file
File diff suppressed because it is too large
Load diff
101
kf_sources/KFStoryGame/Classes/KF_StoryPRI.uc
Normal file
101
kf_sources/KFStoryGame/Classes/KF_StoryPRI.uc
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryPRI
|
||||
--------------------------------------------------------------
|
||||
|
||||
Custom Player ReplicationInfo class for Objective Mode
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class KF_StoryPRI extends KFPlayerReplicationInfo;
|
||||
|
||||
/* Struct that contains information for rendering a hovering icon
|
||||
overtop of a player which is not relevant to clients */
|
||||
|
||||
struct SPlayerIconData
|
||||
{
|
||||
var Material IconMat; // Icon to render over top of the pawn's head.
|
||||
var Vector CurrentPawnLoc; // current location of the player pawn.
|
||||
var Vector LastPawnLoc;
|
||||
};
|
||||
|
||||
var private vector InterpolatedPawnLoc;
|
||||
|
||||
var private SPlayerIconData FloatingIconData;
|
||||
|
||||
/* Reference to the pawn this PRI belongs to */
|
||||
var private KFHumanPawn_Story OwnerPawn;
|
||||
|
||||
var float LastIconUpdateTime;
|
||||
|
||||
replication
|
||||
{
|
||||
unreliable if(Role == Role_Authority && bNetDirty)
|
||||
FloatingIconData,OwnerPawn;
|
||||
|
||||
}
|
||||
|
||||
function SetReplicatedPawnLoc(vector NewLoc)
|
||||
{
|
||||
if(Level.TimeSeconds - LastIconUpdateTime > NetUpdateFrequency)
|
||||
{
|
||||
LastIconUpdateTime = Level.TimeSeconds;
|
||||
FloatingIconData.LastPawnLoc = FloatingIconData.CurrentPawnLoc;
|
||||
}
|
||||
|
||||
if(NewLoc != FloatingIconData.CurrentPawnLoc)
|
||||
{
|
||||
FloatingIconData.CurrentPawnLoc = NewLoc;
|
||||
}
|
||||
}
|
||||
|
||||
function SetOwnerPawn(KFHumanPawn_Story NewOwnerPawn)
|
||||
{
|
||||
OwnerPawn = NewOwnerPawn;
|
||||
}
|
||||
|
||||
function SetFloatingIconMat(material NewMat)
|
||||
{
|
||||
FloatingIconData.IconMat = NewMat;
|
||||
}
|
||||
|
||||
/* Returns the current position of the pawn this PRI belongs to (or as close as we can get) */
|
||||
simulated function Vector GetCurrentPawnLoc()
|
||||
{
|
||||
return FloatingIconData.CurrentPawnLoc;
|
||||
}
|
||||
|
||||
simulated function Vector GetlastPawnLoc()
|
||||
{
|
||||
return FloatingIconData.LastPawnLoc;
|
||||
}
|
||||
|
||||
|
||||
simulated function Vector GetInterpolatedPawnLoc()
|
||||
{
|
||||
return InterpolatedPawnLoc;
|
||||
}
|
||||
|
||||
/* Set on the client only */
|
||||
simulated function SetInterpolatedPawnLoc(vector NewValue)
|
||||
{
|
||||
InterpolatedPawnLoc = NewValue;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the Icon to render overtop of our pawn's head (if one is set) */
|
||||
simulated function Material GetFloatingIconMat()
|
||||
{
|
||||
return FloatingIconData.IconMat;
|
||||
}
|
||||
|
||||
simulated function KFHumanPawn_Story GetOwnerPawn()
|
||||
{
|
||||
return OwnerPawn;
|
||||
}
|
||||
|
||||
|
||||
128
kf_sources/KFStoryGame/Classes/KF_StorySquadDesigner.uc
Normal file
128
kf_sources/KFStoryGame/Classes/KF_StorySquadDesigner.uc
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StorySquadDesigner
|
||||
--------------------------------------------------------------
|
||||
|
||||
This actor provides level designers with a method of settings up
|
||||
pre-defined squads of Monsters for story missions. Squads can be
|
||||
referenced in either KF_StoryZombeVolumes or KF_StoryWaveDesigners.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_StorySquadDesigner extends Info
|
||||
dependson(KFStoryGameInfo)
|
||||
hidecategories(Collision,Force,Karma,Lighting,LightColor,Sound,Events,Movement)
|
||||
placeable;
|
||||
|
||||
|
||||
var() array<KFStoryGameInfo.SZEDSquadType> Squads;
|
||||
var bool bUseDefaultSquads;
|
||||
|
||||
|
||||
/* In case we want to just use whatever is in the KF Gametype instead of having to set up custom monster squads */
|
||||
function FillSquadsFromGameType()
|
||||
{
|
||||
local int i,idx;
|
||||
local KFGameType KFGI;
|
||||
local string SquadString;
|
||||
local array<string> ZEDTypes;
|
||||
local string NewZEDType;
|
||||
local int SplitSize;
|
||||
local string LeftHalf;
|
||||
local int Squadidx;
|
||||
local bool bExistsAlready;
|
||||
|
||||
KFGI = KFGameType(Level.Game);
|
||||
if(KFGI == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SplitSize = 2;
|
||||
|
||||
for(i = 0 ; i < KFGI.MonsterSquad.length ; i ++)
|
||||
{
|
||||
Squads.length = Squads.length + 1;
|
||||
Squads[Squads.length-1].Squad_Name = KFGI.MonsterSquad[i] ;
|
||||
SquadString = Squads[Squads.length-1].Squad_Name ;
|
||||
|
||||
while(Len(SquadString) >= SplitSize)
|
||||
{
|
||||
NewZEDType = Left(SquadString,SplitSize);
|
||||
ZEDTypes[ZEDTypes.length] = NewZEDType;
|
||||
Divide(SquadString,NewZEDType,LeftHalf,SquadString);
|
||||
}
|
||||
|
||||
for(idx = 0 ; idx < ZEDTypes.length ; idx ++)
|
||||
{
|
||||
bExistsAlready = false;
|
||||
for(Squadidx = 0 ; SquadIdx < Squads[Squads.length-1].Squad_ZEDS.length ; SquadIdx ++)
|
||||
{
|
||||
if(string(Squads[Squads.length-1].Squad_ZEDs[SquadIdx].ZEDClass) == ZEDTypes[idx])
|
||||
{
|
||||
bExistsAlready = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bExistsAlready)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Squads[Squads.length-1].Squad_ZEDs.length = Squads[Squads.length-1].Squad_ZEDs.length + 1;
|
||||
Squads[Squads.length-1].Squad_ZEDs[Squads[Squads.length-1].Squad_ZEDs.length -1].ZEDClass = GetAssociatedZEDClass(Right(ZEDTypes[idx],1)) ;
|
||||
Squads[Squads.length-1].Squad_ZEDs[Squads[Squads.length-1].Squad_ZEDs.length -1].NumToSpawn = int(Left(ZEDTypes[idx],1)) ;
|
||||
}
|
||||
}
|
||||
|
||||
ZEDTypes.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returns the class of the ZED associated with the supplied letter ...
|
||||
|
||||
a result of the delightfully overblown Monster Squad system from UT2k4s invasion gametype
|
||||
where a Monster Class is a letter! and a Squad is a bunch of letters! And a Wave is a bunch of
|
||||
bits that represent a bunch of binary which represents a bunch of letters which represent a bunch of Monsters! HERPdeDERPaHURRRRDURRRR !
|
||||
|
||||
*/
|
||||
function class<KFMonster> GetAssociatedZEDClass( string Letter)
|
||||
{
|
||||
local KFGameType KFGI;
|
||||
local int i;
|
||||
local class<KFMonster> ZEDClassType;
|
||||
local string MonsterID;
|
||||
|
||||
KFGI = KFGameType(Level.Game);
|
||||
if(KFGI == none)
|
||||
{
|
||||
return none;
|
||||
}
|
||||
|
||||
for(i = 0 ; i < KFGI.MonsterCollection.default.StandardMonsterClasses.length ; i ++)
|
||||
{
|
||||
MonsterID = KFGI.MonsterCollection.default.StandardMonsterClasses[i].MID ;
|
||||
if(MonsterID == Letter)
|
||||
{
|
||||
ZEDClassType = class<KFMonster>(DynamicLoadObject(KFGI.MonsterCollection.default.StandardMonsterClasses[i].MClassName, class'Class')) ;
|
||||
// log(" The Monster class associated with the letter : "@Letter@"is : "@ZEDClassType.default.menuname,'Story_Debug');
|
||||
return ZEDClassType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DrawScale = 0.5
|
||||
Texture = Texture'KFStoryGame_Tex.Editor.KF_StorySquads_Ico'
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
196
kf_sources/KFStoryGame/Classes/KF_StoryTraderController.uc
Normal file
196
kf_sources/KFStoryGame/Classes/KF_StoryTraderController.uc
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryTraderController
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Actor is used to control the opening / closing of trader shops
|
||||
in story mode missions .
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_StoryTraderController extends info
|
||||
placeable;
|
||||
|
||||
enum EShopAction
|
||||
{
|
||||
Action_OpenCurrentShop,
|
||||
Action_SelectNewShop,
|
||||
};
|
||||
|
||||
var () EShopAction ShopAction;
|
||||
var ShopVolume CurrentShop;
|
||||
var KFGameReplicationInfo KFGRI;
|
||||
|
||||
/* List of shops we want to active / de-activate */
|
||||
var () array<ShopVolume> Shops;
|
||||
|
||||
/* Should we disable player collision when the trader is activated ? */
|
||||
var () bool bDisablePlayerCollision;
|
||||
|
||||
/* Should we remove pickups from the ground when the trader shop closes ? */
|
||||
var () bool bDestroyPickupsOnShopClose;
|
||||
|
||||
event PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
KFGRI = KFGameReplicationInfo(Level.game.GameReplicationInfo) ;
|
||||
}
|
||||
|
||||
function Trigger(Actor Other, Pawn EventInstigator)
|
||||
{
|
||||
switch(ShopAction)
|
||||
{
|
||||
case Action_SelectNewShop :
|
||||
CloseCurrentShop();
|
||||
FindNewShop();
|
||||
break;
|
||||
case Action_OpenCurrentShop :
|
||||
OpenCurrentShop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function OpenCurrentShop()
|
||||
{
|
||||
local Controller C;
|
||||
|
||||
if(GetCurrentShop() == none)
|
||||
{
|
||||
FindNewShop();
|
||||
}
|
||||
|
||||
log("=========================================",'Story_Debug');
|
||||
log("OPEN trader shop : "@GetCurrentShop(),'Story_Debug');
|
||||
|
||||
GetCurrentShop().OpenShop();
|
||||
|
||||
if(KFGameType(Level.Game) != none)
|
||||
{
|
||||
KFGameType(Level.Game).bTradingDoorsOpen = true;
|
||||
}
|
||||
|
||||
/* Maybe disable player collision when the shop is opened ? */
|
||||
if(bDisablePlayerCollision)
|
||||
{
|
||||
for ( C = Level.ControllerList; C != none; C = C.NextController )
|
||||
{
|
||||
if(C.Pawn != none && C.Pawn.Health > 0 )
|
||||
{
|
||||
C.Pawn.bBlockActors = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bool CloseCurrentShop()
|
||||
{
|
||||
local bool bSuccessfulBoot;
|
||||
local Controller C;
|
||||
local WeaponPickup DroppedWeapon;
|
||||
|
||||
if(GetCurrentShop() == none ||
|
||||
!GetCurrentShop().bCurrentlyOpen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
log("=========================================",'Story_Debug');
|
||||
log("CLOSE trader shop : "@GetCurrentShop(),'Story_Debug');
|
||||
|
||||
bSuccessfulBoot = GetCurrentShop().BootPlayers();
|
||||
GetCurrentShop().CloseShop();
|
||||
|
||||
// wait for doors to close before BootPlayers (see KFGameInfo.Timer)
|
||||
SetTimer(1.f, false);
|
||||
|
||||
if( KFGameType(Level.Game) != none)
|
||||
{
|
||||
KFGameType(Level.Game).bTradingDoorsOpen = false;
|
||||
}
|
||||
|
||||
/* Post Buy-Menu garbage collection & Player Collision Handling */
|
||||
for ( C = Level.ControllerList; C != none; C = C.NextController )
|
||||
{
|
||||
/* Maybe turn player collision back on ? */
|
||||
if ( bDisablePlayerCollision &&
|
||||
C.Pawn != none && C.Pawn.Health > 0 )
|
||||
{
|
||||
C.Pawn.bBlockActors = C.Pawn.default.bBlockActors;
|
||||
}
|
||||
|
||||
if(KFPlayerController(C) != none)
|
||||
{
|
||||
KFPlayerController(C).ClientForceCollectGarbage();
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe remove dropped weapons from the ground ? */
|
||||
if(bDestroyPickupsOnShopClose)
|
||||
{
|
||||
foreach AllActors(class'WeaponPickup', DroppedWeapon)
|
||||
{
|
||||
if ( DroppedWeapon.bDropped )
|
||||
{
|
||||
DroppedWeapon.Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!bSuccessfulBoot)
|
||||
{
|
||||
log("WARNING !! - Couldn't boot all players out of Shop : "@GetCurrentShop(),'Story_Debug');
|
||||
}
|
||||
|
||||
return bSuccessfulBoot;
|
||||
|
||||
}
|
||||
|
||||
function Timer()
|
||||
{
|
||||
if(GetCurrentShop() != none && !GetCurrentShop().bCurrentlyOpen)
|
||||
{
|
||||
GetCurrentShop().BootPlayers();
|
||||
}
|
||||
}
|
||||
|
||||
function FindNewShop()
|
||||
{
|
||||
local ShopVolume NewShop;
|
||||
|
||||
if(Shops.length > 0)
|
||||
{
|
||||
NewShop = Shops[Rand(Shops.length)] ;
|
||||
if(NewShop != none)
|
||||
{
|
||||
NewShop.InitTeleports();
|
||||
}
|
||||
}
|
||||
|
||||
if(KFGRI != none)
|
||||
{
|
||||
KFGRI.CurrentShop = NewShop;
|
||||
}
|
||||
|
||||
log("=========================================",'Story_Debug');
|
||||
log("FIND Trader Shop : "@GetCurrentShop(),'Story_Debug');
|
||||
}
|
||||
|
||||
function ShopVolume GetCurrentShop()
|
||||
{
|
||||
if(KFGRI != none)
|
||||
{
|
||||
return KFGRI.CurrentShop ;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bDisablePlayerCollision = true
|
||||
bDestroyPickupsOnShopClose = true
|
||||
|
||||
Texture = Texture'KFStoryGame_Tex.Editor.Trader_ico'
|
||||
}
|
||||
|
||||
262
kf_sources/KFStoryGame/Classes/KF_StoryWaveDesigner.uc
Normal file
262
kf_sources/KFStoryGame/Classes/KF_StoryWaveDesigner.uc
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_StoryWaveDesigner
|
||||
--------------------------------------------------------------
|
||||
|
||||
This actor provides level designers with a method of settings up
|
||||
waves in story missions. It is used in conjunction with either
|
||||
KFZombieVolumes or KFStoryZombieVolumes.
|
||||
|
||||
note : This class just serves as a front end for level designers
|
||||
and a place to declare structs.
|
||||
|
||||
All of the heavy lifting is done in KF_Wave_Controller
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_StoryWaveDesigner extends Info
|
||||
dependson(KFStoryGameInfo)
|
||||
hidecategories(sound)
|
||||
placeable;
|
||||
|
||||
|
||||
enum ESpawnProgressionType
|
||||
{
|
||||
Proceed_On_AllZEDSDead,
|
||||
Proceed_On_AllZEDsSpawned,
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct SWaveSpawn
|
||||
{
|
||||
var() array<string> SquadList;
|
||||
var array<int> SpawnedSquads;
|
||||
var KFStoryGameInfo.SZEDSquadType NextSpawnSquad;
|
||||
var array<KFStoryGameInfo.SZEDSquadType> AllSquads;
|
||||
var() name ZombieDeathEvent;
|
||||
var() name ZombieSpawnTag;
|
||||
var() name ZombieSpawnEvent;
|
||||
var() float SpawnInterval;
|
||||
var() int MaxZEDs;
|
||||
var() bool bNoDifficultyScaling;
|
||||
var() bool bRandomSquadsWithoutRepeats; // Squads will be used in a random order, but will use every squad in the list before starting to go through the list again
|
||||
};
|
||||
|
||||
enum ESineWavePatternUsage
|
||||
{
|
||||
SWP_StartAtMinRate,
|
||||
SWP_StartAtMaxRate,
|
||||
SWP_AlwaysFullSpeed,
|
||||
};
|
||||
|
||||
struct SZEDWave
|
||||
{
|
||||
var bool bKillStragglers;
|
||||
var() array<name> Wave_VolumeTags;
|
||||
var() name Wave_ActivationTag;
|
||||
var() array<SWaveSpawn> Wave_Spawns;
|
||||
var KF_Wave_Controller WaveController;
|
||||
var() ESineWavePatternUsage SineWavePatternUsage;
|
||||
};
|
||||
|
||||
/*==============================================================================*/
|
||||
|
||||
var () array<SZEDWave> Waves;
|
||||
|
||||
var int CurrentWaveIdx;
|
||||
|
||||
enum EWaveProgressType
|
||||
{
|
||||
Procceed_On_AllZEDsSpawned,
|
||||
Proceed_On_AllZEDsKilled,
|
||||
};
|
||||
|
||||
|
||||
var(Debug) bool bPrintDebugLogs;
|
||||
|
||||
/*==============================================================================*/
|
||||
|
||||
|
||||
|
||||
|
||||
function Reset()
|
||||
{
|
||||
local int i;
|
||||
|
||||
for(i = 0 ; i < Waves.length ; i ++)
|
||||
{
|
||||
Waves[i].WaveController.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
function PostBeginPlay()
|
||||
{
|
||||
if(KFStoryGameInfo(Level.Game) != none)
|
||||
{
|
||||
InitWaveControllers();
|
||||
}
|
||||
}
|
||||
|
||||
function InitWaveControllers()
|
||||
{
|
||||
local int i;
|
||||
|
||||
for(i = 0 ; i < Waves.length ; i ++)
|
||||
{
|
||||
SpawnControllerForWave(i);
|
||||
}
|
||||
}
|
||||
|
||||
function SpawnControllerForWave(int Index)
|
||||
{
|
||||
Waves[Index].WaveController = Spawn(class 'KF_Wave_Controller',self);
|
||||
if(Waves[Index].WaveController != none)
|
||||
{
|
||||
Waves[Index].WaveController.SetOwningmanager() ;
|
||||
Waves[Index].WaveController.WaveIndex = Index ;
|
||||
Waves[Index].WaveController.Initialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
log(" === WARNING === could not spawn a WaveController for : "@self@" at Wave Index : "@Index@"!",'Story_Debug');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================================================================================
|
||||
Handy functions ... mostly gonna query the Wave Controller here */
|
||||
|
||||
function KF_Wave_Controller GetCurrentWaveController()
|
||||
{
|
||||
return Waves[CurrentWaveIdx].WaveController ;
|
||||
}
|
||||
|
||||
/* Returns the amount of time between ZED Spawns */
|
||||
function float GetAdjustedSpawninterval()
|
||||
{
|
||||
return GetCurrentWaveController().GetSpawnInterval();
|
||||
}
|
||||
|
||||
/* Grab the total number of ZEDs in the current wave */
|
||||
function int GetWaveMaxMonsters()
|
||||
{
|
||||
return GetCurrentWaveController().GetMaxMonsters();
|
||||
}
|
||||
|
||||
/* Grab the number of ZEDs left alive in the current wave */
|
||||
function int GetWaveRemainingMonsters()
|
||||
{
|
||||
return GetCurrentWaveController().GetRemainingMonsters();
|
||||
}
|
||||
|
||||
function bool IsDirectingSpawnsFor( ZombieVolume TestVol)
|
||||
{
|
||||
return GetCurrentWaveController().IsDirectingSpawnsFor(TestVol);
|
||||
}
|
||||
|
||||
/*
|
||||
function array<class <KFMonster> > GetCurrentZEDList()
|
||||
{
|
||||
return GetCurrentWaveController().GetCurrentZEDList();
|
||||
} */
|
||||
|
||||
function array<class <KFMonster> > GetNextSpawnSquad()
|
||||
{
|
||||
return GetCurrentWaveController().NextSpawnSquad;
|
||||
}
|
||||
|
||||
function int GetWaveByName(name WaveTag)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for(i = 0 ; i < Waves.length ; i ++)
|
||||
{
|
||||
if(Waves[i].Wave_ActivationTag == WaveTag)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=====================================================================================
|
||||
======================================================================================*/
|
||||
// Events ==============================================================================
|
||||
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
GoToNextWave();
|
||||
}
|
||||
|
||||
function GoToNextWave()
|
||||
{
|
||||
if(CurrentWaveidx < Waves.length - 1)
|
||||
{
|
||||
GoToWave(Waves[CurrentWaveIdx + 1].Wave_ActivationTag);
|
||||
}
|
||||
}
|
||||
|
||||
function GoToWave(name WaveTag)
|
||||
{
|
||||
local int i;
|
||||
|
||||
CurrentWaveIdx = GetWaveByName(WaveTag) ;
|
||||
|
||||
/* Abort any other currently active waves in this designer*/
|
||||
for(i = 0 ; i < Waves.length ; i ++)
|
||||
{
|
||||
if(i != CurrentWaveIdx &&
|
||||
Waves[i].WaveController.bActive)
|
||||
{
|
||||
Waves[i].WaveController.AbortWave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*====================================================================================
|
||||
======================================================================================*/
|
||||
|
||||
|
||||
function GetEvents(out array<name> TriggeredEvents, out array<name> ReceivedEvents)
|
||||
{
|
||||
local int i,idx;
|
||||
|
||||
Super.GetEvents(TriggeredEvents,ReceivedEvents);
|
||||
|
||||
for(i = 0 ; i < Waves.length ; i ++)
|
||||
{
|
||||
if(Waves[i].Wave_ActivationTag != '')
|
||||
{
|
||||
ReceivedEvents[ReceivedEvents.length] = Waves[i].Wave_ActivationTag ;
|
||||
}
|
||||
|
||||
for(idx = 0 ; idx < Waves[i].Wave_Spawns.length ; idx ++)
|
||||
{
|
||||
if(Waves[i].Wave_Spawns[idx].ZombieSpawnEvent != '')
|
||||
{
|
||||
TriggeredEvents[TriggeredEvents.length] = Waves[i].Wave_Spawns[idx].ZombieSpawnEvent;
|
||||
}
|
||||
if(Waves[i].Wave_Spawns[idx].ZombieDeathEvent != '')
|
||||
{
|
||||
TriggeredEvents[TriggeredEvents.length] = Waves[i].Wave_Spawns[idx].ZombieDeathEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bStatic = false
|
||||
DrawScale = 0.5
|
||||
Texture = Texture'KFStoryGame_Tex.Editor.KF_StoryWaves_Ico'
|
||||
}
|
||||
|
||||
84
kf_sources/KFStoryGame/Classes/KF_UseableMover.uc
Normal file
84
kf_sources/KFStoryGame/Classes/KF_UseableMover.uc
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KF_UseableMover
|
||||
--------------------------------------------------------------
|
||||
|
||||
A Type of mover that is triggered by 'Use Objectives' in KF Story missions
|
||||
It interpolates while the player is holding the Use key and resets to
|
||||
its original position if the player lets go of the key. (unless the Objective
|
||||
condition is set to keep use progress, in which case it will just freeze
|
||||
where it was at).
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KF_UseableMover extends Mover;
|
||||
|
||||
/* reference to the Use condition which controls this mover's interpolation */
|
||||
var ObjCondition_Use ControllingCondition;
|
||||
|
||||
var float InitialMoveTime;
|
||||
|
||||
/* Interaction stubs - Called by the Controlling Condition */
|
||||
function Startedusing();
|
||||
function StoppedUsing();
|
||||
|
||||
|
||||
/* Called when a use condition 'possesses' this Mover */
|
||||
function Notify_Controlled(ObjCondition_Use NewController)
|
||||
{
|
||||
if(NewController != none)
|
||||
{
|
||||
ControllingCondition = NewController;
|
||||
InitialMoveTime = ControllingCondition.GetRemainingUseTime() ;
|
||||
MoveTime = InitialMoveTime;
|
||||
|
||||
InitialState = 'UseControlled' ;
|
||||
Backup_InitialState = InitialState;
|
||||
GoToState('UseControlled');
|
||||
}
|
||||
}
|
||||
|
||||
/* state the mover enters when it is being controlled by a player */
|
||||
state UseControlled
|
||||
{
|
||||
function StartedUsing()
|
||||
{
|
||||
InitialMoveTime = ControllingCondition.GetRemainingUseTime() ;
|
||||
MoveTime = InitialMoveTime;
|
||||
GoToState('UseControlled','Open');
|
||||
}
|
||||
|
||||
function StoppedUsing()
|
||||
{
|
||||
if(ControllingCondition.bKeepUseProgress)
|
||||
{
|
||||
GoToState('UseControlled','Freeze');
|
||||
}
|
||||
else
|
||||
{
|
||||
InitialMoveTime = ControllingCondition.GetRemainingUseTime() * 0.1 ;
|
||||
MoveTime = InitialMoveTime;
|
||||
GoToState('UseControlled','Close');
|
||||
}
|
||||
}
|
||||
|
||||
Open:
|
||||
bClosed = false;
|
||||
DoOpen();
|
||||
FinishInterpolation();
|
||||
FinishedOpening();
|
||||
Stop;
|
||||
Close:
|
||||
DoClose();
|
||||
FinishInterpolation();
|
||||
FinishedClosing();
|
||||
SetResetStatus( false );
|
||||
Freeze:
|
||||
bInterpolating = false;
|
||||
FinishInterpolation();
|
||||
}
|
||||
|
||||
|
||||
1025
kf_sources/KFStoryGame/Classes/KF_Wave_Controller.uc
Normal file
1025
kf_sources/KFStoryGame/Classes/KF_Wave_Controller.uc
Normal file
File diff suppressed because it is too large
Load diff
45
kf_sources/KFStoryGame/Classes/KeyPickup_Story.uc
Normal file
45
kf_sources/KFStoryGame/Classes/KeyPickup_Story.uc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
KeyPickup_Story
|
||||
--------------------------------------------------------------
|
||||
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class KeyPickup_Story extends WeaponPickup;
|
||||
|
||||
/*
|
||||
function inventory SpawnCopy( pawn Other )
|
||||
{
|
||||
local inventory KeyInv;
|
||||
|
||||
KeyInv = Super.SpawnCopy(Other);
|
||||
KeyInv.Tag = Tag;
|
||||
|
||||
if( KFKeyInventory(KeyInv)!=None )
|
||||
{
|
||||
KFKeyInventory(KeyInv).MyPickup = self;
|
||||
}
|
||||
|
||||
return Copy;
|
||||
}*/
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
InventoryType=Class'KFMod.KFKeyInventory'
|
||||
PickupMessage="You found a key"
|
||||
PickupSound=Sound'PatchSounds.slide1-3'
|
||||
DrawType=DT_StaticMesh
|
||||
StaticMesh=StaticMesh'KillingFloorLabStatics.KeyCard1'
|
||||
Physics=PHYS_Falling
|
||||
DrawScale=0.100000
|
||||
AmbientGlow=40
|
||||
UV2Texture=FadeColor'PatchTex.Common.PickupOverlay'
|
||||
CollisionRadius=20.000000
|
||||
CollisionHeight=5.000000
|
||||
MessageClass=Class'UnrealGame.PickupMessagePlus'
|
||||
}
|
||||
34
kf_sources/KFStoryGame/Classes/Msg_CashReward.uc
Normal file
34
kf_sources/KFStoryGame/Classes/Msg_CashReward.uc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
class Msg_CashReward extends LocalMessage;
|
||||
|
||||
static function string GetString(
|
||||
optional int Switch,
|
||||
optional PlayerReplicationInfo RelatedPRI_1,
|
||||
optional PlayerReplicationInfo RelatedPRI_2,
|
||||
optional Object OptionalObject
|
||||
)
|
||||
{
|
||||
if(Switch > 0)
|
||||
{
|
||||
return "+ £"@Switch ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "- £"@Switch ;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bIsConsoleMessage=false
|
||||
DrawColor=(B=100,G=255,R=100,A=255)
|
||||
Lifetime=5
|
||||
FontSize=2
|
||||
bBeep=False
|
||||
bFadeMessage=True
|
||||
bIsUnique=False
|
||||
StackMode=SM_Up
|
||||
|
||||
PosX = 0.92
|
||||
PosY = 0.82
|
||||
}
|
||||
|
||||
52
kf_sources/KFStoryGame/Classes/Msg_CheckPoint.uc
Normal file
52
kf_sources/KFStoryGame/Classes/Msg_CheckPoint.uc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Msg_CheckPoint
|
||||
--------------------------------------------------------------
|
||||
|
||||
Notification that a checkpoint was reached
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Msg_CheckPoint extends LocalMessage;
|
||||
|
||||
var string CheckPointStrings[2];
|
||||
|
||||
|
||||
static function string GetString(
|
||||
optional int Switch,
|
||||
optional PlayerReplicationInfo RelatedPRI_1,
|
||||
optional PlayerReplicationInfo RelatedPRI_2,
|
||||
optional Object OptionalObject
|
||||
)
|
||||
{
|
||||
local string FinalString;
|
||||
local KF_StoryCheckPointVolume CheckPoint;
|
||||
|
||||
CheckPoint = KF_StoryCheckPointVolume(OptionalObject);
|
||||
|
||||
switch(Switch)
|
||||
{
|
||||
case 0 : FinalString = RelatedPRI_1.PlayerName@default.CheckPointStrings[0]@CheckPoint.CheckPointName ; break;
|
||||
case 1 : FinalString = default.CheckPointStrings[1]@CheckPoint.CheckPointName ; break;
|
||||
}
|
||||
|
||||
return FinalString;
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
CheckPointStrings(0)="reached"
|
||||
CheckPointStrings(1)="Your team will respawn at .."
|
||||
|
||||
bIsConsoleMessage=False
|
||||
bFadeMessage=True
|
||||
Lifetime=5
|
||||
DrawColor=(R=25,B=255,G=150)
|
||||
PosY=0.5
|
||||
FontSize=2
|
||||
bIsUnique = false
|
||||
}
|
||||
67
kf_sources/KFStoryGame/Classes/Msg_EyeBallNotification.uc
Normal file
67
kf_sources/KFStoryGame/Classes/Msg_EyeBallNotification.uc
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Msg_EyeBallNotification
|
||||
--------------------------------------------------------------
|
||||
|
||||
Local Message class for Patriarch's Eyeball
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Msg_EyeBallNotification extends WaitingMessage;
|
||||
|
||||
var localized string EyeWasPickedUpString;
|
||||
var localized string EyeWasDroppedString;
|
||||
var localized string EyeWasScannedString;
|
||||
|
||||
static function string GetString(
|
||||
optional int Switch,
|
||||
optional PlayerReplicationInfo RelatedPRI_1,
|
||||
optional PlayerReplicationInfo RelatedPRI_2,
|
||||
optional Object OptionalObject
|
||||
)
|
||||
{
|
||||
switch(Switch)
|
||||
{
|
||||
case 1 : // Someone picked up the eye
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.EyeWasPickedUpString ;
|
||||
|
||||
case 2 : // Someone dropped the eye
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.EyeWasDroppedString ;
|
||||
|
||||
case 3 : // Someone used the eye on the retinal scanner.
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.EyeWasScannedString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static function GetPos(int Switch, out EDrawPivot OutDrawPivot, out EStackMode OutStackMode, out float OutPosX, out float OutPosY)
|
||||
{
|
||||
OutDrawPivot = default.DrawPivot;
|
||||
OutStackMode = default.StackMode;
|
||||
OutPosX = default.PosX;
|
||||
OutPosY = 0.7;
|
||||
}
|
||||
|
||||
static function float GetLifeTime(int Switch)
|
||||
{
|
||||
return default.LifeTime;
|
||||
}
|
||||
|
||||
static function int GetFontSize(int Switch, PlayerReplicationInfo RelatedPRI1, PlayerReplicationInfo RelatedPRI2, PlayerReplicationInfo LocalPlayer)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Lifetime=4
|
||||
DrawColor=(R=255,G=25,B=25)
|
||||
|
||||
EyeWasPickedUpString = "picked up the Patriarch's eyeball"
|
||||
EyeWasDroppedString = "dropped the Patriarch's eyeball"
|
||||
EyeWasScannedString = "used the Patriarch's eyeball on the retinal scanner."
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Msg_MaintenanceKeyCardNotification
|
||||
--------------------------------------------------------------
|
||||
|
||||
Local Message class for the Subway Maintenance keycard
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Msg_MaintenanceKeyCardNotification extends WaitingMessage;
|
||||
|
||||
var localized string KeyCardPickedUpString;
|
||||
var localized string KeyCardDroppedString;
|
||||
|
||||
static function string GetString(
|
||||
optional int Switch,
|
||||
optional PlayerReplicationInfo RelatedPRI_1,
|
||||
optional PlayerReplicationInfo RelatedPRI_2,
|
||||
optional Object OptionalObject
|
||||
)
|
||||
{
|
||||
switch(Switch)
|
||||
{
|
||||
case 1 : // Someone picked up the keycard.
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.KeyCardPickedUpString ;
|
||||
|
||||
case 2 : // Someone dropped the keycard.
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.KeyCardDroppedString ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static function GetPos(int Switch, out EDrawPivot OutDrawPivot, out EStackMode OutStackMode, out float OutPosX, out float OutPosY)
|
||||
{
|
||||
OutDrawPivot = default.DrawPivot;
|
||||
OutStackMode = default.StackMode;
|
||||
OutPosX = default.PosX;
|
||||
OutPosY = 0.7;
|
||||
}
|
||||
|
||||
static function float GetLifeTime(int Switch)
|
||||
{
|
||||
return default.LifeTime;
|
||||
}
|
||||
|
||||
static function int GetFontSize(int Switch, PlayerReplicationInfo RelatedPRI1, PlayerReplicationInfo RelatedPRI2, PlayerReplicationInfo LocalPlayer)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Lifetime=4
|
||||
DrawColor=(R=255,G=25,B=25)
|
||||
|
||||
KeyCardPickedUpString = "picked up the Maintenance Keycard"
|
||||
KeyCardDroppedString = "dropped the Maintenance KeyCard"
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Msg_NitroglycerinNotification
|
||||
--------------------------------------------------------------
|
||||
|
||||
Local Message class for the Nitroglycerin
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Msg_NitroglycerinNotification extends WaitingMessage;
|
||||
|
||||
var localized string NitroglycerinPickedUpString;
|
||||
var localized string NitroglycerinDroppedString;
|
||||
|
||||
static function string GetString(
|
||||
optional int Switch,
|
||||
optional PlayerReplicationInfo RelatedPRI_1,
|
||||
optional PlayerReplicationInfo RelatedPRI_2,
|
||||
optional Object OptionalObject
|
||||
)
|
||||
{
|
||||
switch(Switch)
|
||||
{
|
||||
case 1 : // Someone picked up the Nitroglycerin
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.NitroglycerinPickedUpString ;
|
||||
|
||||
case 2 : // Someone dropped the Nitroglycerin
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.NitroglycerinDroppedString ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static function GetPos(int Switch, out EDrawPivot OutDrawPivot, out EStackMode OutStackMode, out float OutPosX, out float OutPosY)
|
||||
{
|
||||
OutDrawPivot = default.DrawPivot;
|
||||
OutStackMode = default.StackMode;
|
||||
OutPosX = default.PosX;
|
||||
OutPosY = 0.7;
|
||||
}
|
||||
|
||||
static function float GetLifeTime(int Switch)
|
||||
{
|
||||
return default.LifeTime;
|
||||
}
|
||||
|
||||
static function int GetFontSize(int Switch, PlayerReplicationInfo RelatedPRI1, PlayerReplicationInfo RelatedPRI2, PlayerReplicationInfo LocalPlayer)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Lifetime=4
|
||||
DrawColor=(R=255,G=25,B=25)
|
||||
|
||||
NitroglycerinPickedUpString = "picked up the Nitroglycerin"
|
||||
NitroglycerinDroppedString = "dropped the Nitroglycerin"
|
||||
}
|
||||
61
kf_sources/KFStoryGame/Classes/Msg_ThermiteNotification.uc
Normal file
61
kf_sources/KFStoryGame/Classes/Msg_ThermiteNotification.uc
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Msg_ThermiteNotification
|
||||
--------------------------------------------------------------
|
||||
|
||||
Local Message class for the Thermite pickup
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Msg_ThermiteNotification extends WaitingMessage;
|
||||
|
||||
var localized string ThermitePickedUpString;
|
||||
var localized string ThermiteDroppedString;
|
||||
|
||||
static function string GetString(
|
||||
optional int Switch,
|
||||
optional PlayerReplicationInfo RelatedPRI_1,
|
||||
optional PlayerReplicationInfo RelatedPRI_2,
|
||||
optional Object OptionalObject
|
||||
)
|
||||
{
|
||||
switch(Switch)
|
||||
{
|
||||
case 1 : // Someone picked up the Thermite
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.ThermitePickedUpString ;
|
||||
|
||||
case 2 : // Someone dropped the Thermite
|
||||
|
||||
return RelatedPRI_1.PlayerName@default.ThermiteDroppedString ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static function GetPos(int Switch, out EDrawPivot OutDrawPivot, out EStackMode OutStackMode, out float OutPosX, out float OutPosY)
|
||||
{
|
||||
OutDrawPivot = default.DrawPivot;
|
||||
OutStackMode = default.StackMode;
|
||||
OutPosX = default.PosX;
|
||||
OutPosY = 0.7;
|
||||
}
|
||||
|
||||
static function float GetLifeTime(int Switch)
|
||||
{
|
||||
return default.LifeTime;
|
||||
}
|
||||
|
||||
static function int GetFontSize(int Switch, PlayerReplicationInfo RelatedPRI1, PlayerReplicationInfo RelatedPRI2, PlayerReplicationInfo LocalPlayer)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Lifetime=4
|
||||
DrawColor=(R=255,G=25,B=25)
|
||||
|
||||
ThermitePickedUpString = "picked up the Thermite"
|
||||
ThermiteDroppedString = "dropped the Thermite"
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//-----------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
class ObjAction_GoToLastObjective extends ObjAction_GoToObjective
|
||||
hideCategories(KF_ObjectiveAction)
|
||||
editinlinenew;
|
||||
|
||||
function name GetTargetObj()
|
||||
{
|
||||
/* Last objective only returns anything meaningful at runtime */
|
||||
if(GetObjOwner() != none && GetObjOwner().StoryGI != none)
|
||||
{
|
||||
return GetObjOwner().StoryGI.LastObjective.ObjectiveName ;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
112
kf_sources/KFStoryGame/Classes/ObjAction_GoToNextObjective.uc
Normal file
112
kf_sources/KFStoryGame/Classes/ObjAction_GoToNextObjective.uc
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Action_GoToNextObjective
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Action changes the current objective to the next one
|
||||
in the sorted Objectives list defined in the Level Rules actor.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjAction_GoToNextObjective extends ObjAction_GoToObjective
|
||||
hideCategories(KF_ObjectiveAction)
|
||||
editinlinenew;
|
||||
|
||||
/* Offset to apply to ObjectiveIndex. ie. We want to skip forward to the next,NEXT objective. (offset=1) */
|
||||
var () int Offset;
|
||||
|
||||
/* if not null, Go to the next objective that has this tag */
|
||||
var () name NextObjTag;
|
||||
|
||||
/* At Runtime query the gameinfo to figure out what the next objective is. Otherwise use the list
|
||||
in the levelinfo */
|
||||
|
||||
function name GetTargetObj()
|
||||
{
|
||||
local array<StoryObjectiveBase> ObjectiveList;
|
||||
local int i,ObjIdx;
|
||||
|
||||
if(GetObjOwner() != none && GetObjOwner().StoryGI != none) // runtime.
|
||||
{
|
||||
ObjectiveList = GetObjOwner().StoryGI.SortedObjectives ;
|
||||
ObjIdx = GetObjOwner().StoryGI.CurrentObjectiveIdx;
|
||||
}
|
||||
|
||||
if(NextObjTag == '')
|
||||
{
|
||||
return ObjectiveList[ ObjIdx + (1 + Offset) ].ObjectiveName ;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = (ObjIdx + (1 + Offset)) ; i < ObjectiveList.length ; i ++)
|
||||
{
|
||||
if(ObjectiveList[i].tag == NextObjTag)
|
||||
{
|
||||
return ObjectiveList[i].ObjectiveName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log("Warning - Could not find any objectives with tag : "@NextObjTag@" in the Sorted Objectives array."@self@" will fail. ");
|
||||
return '';
|
||||
}
|
||||
|
||||
function StoryObjectiveBase GetNextEditorObj(StoryObjectiveBase Sender, array<StoryObjectiveBase> ObjList)
|
||||
{
|
||||
local int i,idx,ObjIdx;
|
||||
local LevelInfo LI;
|
||||
local array<StoryObjectiveBase> SortedObjList;
|
||||
|
||||
if(Sender == none)
|
||||
{
|
||||
return none;
|
||||
}
|
||||
|
||||
LI = Sender.Level ;
|
||||
|
||||
/* Build a list of the linear objectives in the map */
|
||||
SortedObjList.length = LI.StoryObjectives.length;
|
||||
|
||||
for(i = 0 ; i < ObjList.length ; i ++)
|
||||
{
|
||||
for(idx = 0 ; idx < LI.StoryObjectives.length ; idx++)
|
||||
{
|
||||
if(ObjList[i].ObjectiveName == LI.StoryObjectives[idx])
|
||||
{
|
||||
SortedObjList[idx] = ObjList[i] ;
|
||||
}
|
||||
|
||||
if(SortedObjList[idx] == Sender)
|
||||
{
|
||||
ObjIdx = idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjList = SortedObjList;
|
||||
|
||||
if(NextObjTag == '')
|
||||
{
|
||||
return ObjList[ ObjIdx + (1 + Offset) ];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = (ObjIdx + (1 + Offset)) ; i < ObjList.length ; i ++)
|
||||
{
|
||||
if(ObjList[i].tag == NextObjTag)
|
||||
{
|
||||
return ObjList[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return none;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
65
kf_sources/KFStoryGame/Classes/ObjAction_GoToObjective.uc
Normal file
65
kf_sources/KFStoryGame/Classes/ObjAction_GoToObjective.uc
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Action_GoToObjective
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Action changes the current objective to the one specified
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjAction_GoToObjective extends KF_ObjectiveAction
|
||||
editinlinenew;
|
||||
|
||||
function ExecuteAction(Controller ActionInstigator)
|
||||
{
|
||||
Super.ExecuteAction(ActionInstigator);
|
||||
GetObjOwner().StoryGI.SetActiveObjective(GetObjOwner().StoryGI.FindObjectiveNamed(GetTargetObj()),ActionInstigator.Pawn) ;
|
||||
}
|
||||
|
||||
function bool IsValidActionFor(KF_StoryObjective Obj)
|
||||
{
|
||||
local KF_StoryObjective TargetObj;
|
||||
|
||||
TargetObj = Obj.StoryGI.FindObjectiveNamed(GetTargetObj());
|
||||
if(TargetObj != none)
|
||||
{
|
||||
return TargetObj.IsValidForActivation();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function name GetTargetObj()
|
||||
{
|
||||
return ObjectiveName;
|
||||
}
|
||||
|
||||
|
||||
function StoryObjectiveBase GetNextEditorObj(StoryObjectiveBase Sender, array<StoryObjectiveBase> ObjList)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(ObjectiveName != '')
|
||||
{
|
||||
for(i = 0 ; i < ObjList.length ; i ++)
|
||||
{
|
||||
if(ObjList[i].ObjectiveName == ObjectiveName)
|
||||
{
|
||||
return ObjList[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
26
kf_sources/KFStoryGame/Classes/ObjAction_LoseGame.uc
Normal file
26
kf_sources/KFStoryGame/Classes/ObjAction_LoseGame.uc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Action_LoseGame
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Action ends the match in defeat, when Activated.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjAction_LoseGame extends KF_ObjectiveAction
|
||||
editinlinenew
|
||||
HideCategories(KF_ObjectiveAction);
|
||||
|
||||
function ExecuteAction(Controller ActionInstigator)
|
||||
{
|
||||
Super.ExecuteAction(ActionInstigator);
|
||||
GetObjOwner().StoryGI.EndGame(ActionInstigator.PlayerReplicationinfo, "LoseAction") ;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
98
kf_sources/KFStoryGame/Classes/ObjAction_Random.uc
Normal file
98
kf_sources/KFStoryGame/Classes/ObjAction_Random.uc
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Action_Random
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Action serves as a container for any number of other Actions.
|
||||
when initalized, it picks one at random and activates it.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjAction_Random extends KF_ObjectiveAction
|
||||
editinlinenew
|
||||
HideCategories(KF_ObjectiveAction);
|
||||
|
||||
struct SRandomAction
|
||||
{
|
||||
var () editinlineuse KF_ObjectiveAction Action;
|
||||
|
||||
var () int Priority;
|
||||
};
|
||||
|
||||
|
||||
var (Actions) float PriorityBias;
|
||||
|
||||
var (Actions) editinlineuse array<SRandomAction> RandomActions;
|
||||
|
||||
|
||||
var int RandIdx;
|
||||
|
||||
|
||||
function ExecuteAction(Controller ActionInstigator)
|
||||
{
|
||||
Super.ExecuteAction(ActionInstigator);
|
||||
AssignRandomAction(ActionInstigator);
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
super.Reset();
|
||||
SwapAction(self);
|
||||
}
|
||||
|
||||
|
||||
function AssignRandomAction(Controller ActionInstigator)
|
||||
{
|
||||
local float HighestRating;
|
||||
local float PriorityVal;
|
||||
local int BestIdx;
|
||||
local array<float> Ratings;
|
||||
local int i,idx;
|
||||
|
||||
HighestRating = -1;
|
||||
BestIdx = -1;
|
||||
|
||||
for(i = 0 ; i < RandomActions.length ; i ++)
|
||||
{
|
||||
PriorityVal = RandomActions[i].Priority ;
|
||||
Ratings[i] = RandRange( FMin(Ratings[idx] * PriorityBias,Ratings[idx]) , PriorityVal ) ;
|
||||
}
|
||||
|
||||
for(idx = 0 ; idx < Ratings.length ; idx ++)
|
||||
{
|
||||
if(Ratings[idx] > highestRating &&
|
||||
RandomActions[idx].Action.IsValidActionFor(GetObjOwner()) )
|
||||
{
|
||||
BestIdx = idx;
|
||||
HighestRating = Ratings[idx] ;
|
||||
}
|
||||
}
|
||||
|
||||
if(BestIdx < 0 || BestIdx >= RandomActions.length)
|
||||
{
|
||||
log("Warning - Cannot find a valid action for : "@self@" Random action will fail. ",'Story_Debug');
|
||||
}
|
||||
|
||||
RandIdx = BestIdx;
|
||||
RandomActions[RandIdx].Action.ActionType = ActionType;
|
||||
RandomActions[RandIdx].Action.SetObjOwner(GetObjOwner());
|
||||
SwapAction(RandomActions[RandIdx].Action) ;
|
||||
RandomActions[RandIdx].Action.ExecuteAction(ActionInstigator);
|
||||
}
|
||||
|
||||
function SwapAction(KF_ObjectiveAction SwapAction)
|
||||
{
|
||||
switch(ActionType)
|
||||
{
|
||||
case 0 : GetObjOwner().FailureAction = SwapAction; break;
|
||||
case 1 : GetObjOwner().SuccessAction = SwapAction; break;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
PriorityBias = 0.5
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Action_ResetCurrentObjective
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Action resets the currently active objective to the state it was in when it was first activated.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjAction_ResetCurrentObjective extends KF_ObjectiveAction
|
||||
editinlinenew
|
||||
HideCategories(KF_ObjectiveAction);
|
||||
|
||||
function ExecuteAction(Controller ActionInstigator)
|
||||
{
|
||||
Super.ExecuteAction(ActionInstigator);
|
||||
|
||||
if(GetObjOwner() != none)
|
||||
{
|
||||
GetObjOwner().StoryGI.CurrentObjective.Reset();
|
||||
GetObjOwner().StoryGI.CurrentObjective.Notify_ConditionsActivated(ActionInstigator.Pawn);
|
||||
}
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Action_RestartFromCheckPoint
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Action forces players to respawn from the last activated checkpoint
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjAction_RestartFromCheckPoint extends KF_ObjectiveAction
|
||||
editinlinenew
|
||||
HideCategories(KF_ObjectiveAction);
|
||||
|
||||
function ExecuteAction(Controller ActionInstigator)
|
||||
{
|
||||
Super.ExecuteAction(ActionInstigator);
|
||||
GetObjOwner().StoryGI.RestartEveryone() ;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
26
kf_sources/KFStoryGame/Classes/ObjAction_WinGame.uc
Normal file
26
kf_sources/KFStoryGame/Classes/ObjAction_WinGame.uc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Action_WinGame
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Action ends the match in victory, when Activated.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjAction_WinGame extends KF_ObjectiveAction
|
||||
editinlinenew
|
||||
HideCategories(KF_ObjectiveAction);
|
||||
|
||||
function ExecuteAction(Controller ActionInstigator)
|
||||
{
|
||||
Super.ExecuteAction(ActionInstigator);
|
||||
GetObjOwner().StoryGI.EndGame(ActionInstigator.PlayerReplicationInfo,"WinAction");
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
234
kf_sources/KFStoryGame/Classes/ObjCondition_ActorHealth.uc
Normal file
234
kf_sources/KFStoryGame/Classes/ObjCondition_ActorHealth.uc
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_ActorHealth
|
||||
--------------------------------------------------------------
|
||||
|
||||
A Condition which tracks the health state of specified Actor(s)
|
||||
and is marked complete when it drops below a specified threshold.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_ActorHealth extends KF_ObjectiveCondition
|
||||
editinlinenew;
|
||||
|
||||
enum EHealthMethod
|
||||
{
|
||||
Health_Empty,
|
||||
Health_Full,
|
||||
};
|
||||
|
||||
var () edfindable private Actor TargetActor;
|
||||
|
||||
var bool bAcquiredPawn;
|
||||
/* if we are defending a pawn, this is the minimum health that pawn can drop to before we fail */
|
||||
var () float MinHealthPct;
|
||||
/* tag for actors that are spawned at runtime which we must also defend */
|
||||
var () Name TargetPawnTag;
|
||||
|
||||
var () EHealthMethod HealthCondition;
|
||||
|
||||
var float CurrentHealth,HealthMax;
|
||||
|
||||
var const name InitialHealthActorName,HealthActorName;
|
||||
|
||||
function PostBeginPlay(KF_StoryObjective MyOwner)
|
||||
{
|
||||
Super.PostBeginPlay(MyOwner);
|
||||
|
||||
// Ditch any reference to this actor ASAP.
|
||||
if(TargetActor != none)
|
||||
{
|
||||
SetTargetActor(HealthActorName,TargetActor);
|
||||
SetTargetActor(InitialHealthActorName,TargetActor);
|
||||
TargetActor = none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
CurrentHealth = 0;
|
||||
HealthMax = 0;
|
||||
bAcquiredPawn = false;
|
||||
}
|
||||
|
||||
function ConditionActivated(pawn ActivatingPlayer)
|
||||
{
|
||||
local Actor InitialActor;
|
||||
|
||||
Super.ConditionActivated(ActivatingPlayer);
|
||||
|
||||
InitialActor = GetTargetActor(InitialHealthActorName) ;
|
||||
|
||||
if(InitialActor != none &&
|
||||
!InitialActor.bPendingDelete)
|
||||
{
|
||||
SetTargetActor(HealthActorName,InitialActor);
|
||||
}
|
||||
}
|
||||
|
||||
function bool ConditionIsRelevant()
|
||||
{
|
||||
local Actor MyTargetActor;
|
||||
|
||||
MyTargetActor = GetTargetActor(HealthActorName);
|
||||
|
||||
if(MyTargetActor != none &&
|
||||
KF_StoryNPC(MyTargetActor) != none)
|
||||
{
|
||||
return KF_StoryNPC(MyTargetActor).bActive ;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
local KFDoorMover DoorActor;
|
||||
local Pawn PawnActor;
|
||||
local Actor MyTargetActor;
|
||||
|
||||
UpdatePawnList();
|
||||
|
||||
MyTargetActor = GetTargetActor(HealthActorName);
|
||||
|
||||
if(MyTargetActor != none &&
|
||||
!MyTargetActor.bDeleteMe &&
|
||||
!MyTargetActor.bPendingDelete)
|
||||
{
|
||||
PawnActor = Pawn(MyTargetActor);
|
||||
DoorActor = KFDoorMover(MyTargetActor);
|
||||
|
||||
if(DoorActor != none && DoorActor.MyTrigger != none )
|
||||
{
|
||||
HealthMax = DoorActor.MyTrigger.MaxWeldStrength ;
|
||||
CurrentHealth = DoorActor.MyTrigger.WeldStrength ;
|
||||
}
|
||||
else
|
||||
if(PawnActor != none)
|
||||
{
|
||||
HealthMax = PawnActor.HealthMax;
|
||||
CurrentHealth = PawnActor.Health;
|
||||
}
|
||||
else
|
||||
{
|
||||
HealthMax = 100.f;
|
||||
CurrentHealth = float(MyTargetActor != none && !MyTargetActor.bHidden && !MyTargetActor.bPendingDelete) * 100.f ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentHealth = 0;
|
||||
}
|
||||
|
||||
Super.ConditionTick(DeltaTime);
|
||||
}
|
||||
|
||||
|
||||
function UpdatePawnList()
|
||||
{
|
||||
local Controller C;
|
||||
local Actor MyTargetActor;
|
||||
|
||||
MyTargetActor = GetTargetActor(HealthActorName);
|
||||
|
||||
if(bAcquiredPawn ||
|
||||
TargetpawnTag == '' ||
|
||||
(MyTargetActor != none &&
|
||||
MyTargetActor.Tag == TargetPawnTag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( C= GetObjOwner().Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if(C.Pawn != none &&
|
||||
!C.Pawn.bDeleteMe &&
|
||||
!C.Pawn.bPendingDelete &&
|
||||
C.Pawn.Health > 0 &&
|
||||
C.Pawn.Tag == TargetpawnTag)
|
||||
{
|
||||
SetTargetActor(HealthActorName,C.Pawn);
|
||||
bAcquiredPawn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function vector GetLocation(optional out Actor LocActor)
|
||||
{
|
||||
local Actor MyTargetActor;
|
||||
local Actor HUDWorldLocActor;
|
||||
|
||||
if(ConditionIsActive())
|
||||
{
|
||||
MyTargetActor = GetTargetActor(HealthActorName);
|
||||
|
||||
if(MyTargetActor != none &&
|
||||
!MyTargetActor.bPendingDelete)
|
||||
{
|
||||
LocActor = MyTargetActor;
|
||||
return MyTargetActor.Location ;
|
||||
}
|
||||
|
||||
HUDWorldLocActor = GetTargetActor(WorldLocActorName);
|
||||
if( HUDWorldLocActor != none)
|
||||
{
|
||||
LocActor = HUDWorldLocActor ;
|
||||
return HUDWorldLocActor.Location ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return vect(0,0,0); // force not to display.
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
local float Pct;
|
||||
|
||||
if(HealthMax == 0)
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
if(HealthCondition == Health_Empty)
|
||||
{
|
||||
Pct = 1.f - FClamp(CurrentHealth / HealthMax,0.f,1.f) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pct = FClamp(CurrentHealth / HealthMax,0.f,1.f) ;
|
||||
}
|
||||
|
||||
return Pct;
|
||||
}
|
||||
|
||||
function string GetDataString()
|
||||
{
|
||||
if(HUD_Screen.Screen_CountStyle == 1)
|
||||
{
|
||||
return Int(Round((1.f-GetCompletionPct())*100))$"%" ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Int(Round((GetCompletionPct())*100))$"%" ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
InitialHealthActorName = "InitialHealthActor"
|
||||
HealthActorName = "HealthActor"
|
||||
}
|
||||
|
||||
|
||||
327
kf_sources/KFStoryGame/Classes/ObjCondition_Area.uc
Normal file
327
kf_sources/KFStoryGame/Classes/ObjCondition_Area.uc
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Area
|
||||
--------------------------------------------------------------
|
||||
|
||||
A Condition which is marked complete when a player either
|
||||
(A) leaves a volume or (B) enters a volume
|
||||
Can also be configured to check ZoneInfo regions.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_Area extends KF_ObjectiveCondition
|
||||
editinlinenew;
|
||||
|
||||
var () private edfindable Volume AreaVolume;
|
||||
|
||||
var const Name AreaVolumeName,InitialAreaVolumeName;
|
||||
|
||||
var () string AreaZoneName;
|
||||
|
||||
var private Volume InitialVolume;
|
||||
|
||||
var () float Duration;
|
||||
|
||||
var () bool bRequiresWholeTeam;
|
||||
|
||||
var private ZoneInfo AssociatedZone; // Zones are NoDelete so having a reference in here should be O.K
|
||||
|
||||
|
||||
enum EAreaConditionType
|
||||
{
|
||||
Method_LeaveArea,
|
||||
Method_EnterArea,
|
||||
};
|
||||
|
||||
var ()class<Actor> ProximityTriggerType;
|
||||
|
||||
var () name ProximityTag;
|
||||
|
||||
var ()EAreaConditionType CompletionMethod;
|
||||
|
||||
var () bool bKeepProgress;
|
||||
|
||||
var float LastInAreaTime;
|
||||
|
||||
var float TimeInArea;
|
||||
|
||||
var float TimeOutOfArea;
|
||||
|
||||
var float LastOutOfAreaTime;
|
||||
|
||||
var bool bTimingOut;
|
||||
|
||||
var int NumInVolume;
|
||||
|
||||
var private array<name> PawnInstigatorNames;
|
||||
|
||||
function PostBeginPlay(KF_StoryObjective MyOwner)
|
||||
{
|
||||
local ZoneInfo Zone;
|
||||
|
||||
Super.PostBeginPlay(MyOwner);
|
||||
|
||||
if(AreaVolume != none)
|
||||
{
|
||||
SetTargetActor(InitialAreaVolumeName,AreaVolume);
|
||||
SetTargetActor(AreaVolumeName,AreaVolume);
|
||||
AreaVolume = none;
|
||||
}
|
||||
else if(AreaZoneName != "")
|
||||
{
|
||||
foreach AllObjects(class 'ZoneInfo', Zone)
|
||||
{
|
||||
if(Zone.LocationName == AreaZoneName)
|
||||
{
|
||||
AssociatedZone = Zone;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function array<Pawn> GetInstigatorList()
|
||||
{
|
||||
local array<Pawn> PawnInstigators;
|
||||
local int i;
|
||||
|
||||
for(i = 0 ; i < PawnInstigatorNames.length ; i ++)
|
||||
{
|
||||
PawnInstigators[PawnInstigators.length] = Pawn(GetTargetActor(PawnInstigatorNames[i])) ;
|
||||
}
|
||||
|
||||
return PawnInstigators;
|
||||
}
|
||||
|
||||
function AdjustToDifficulty(float Difficulty)
|
||||
{
|
||||
Duration /= FMax(Difficulty-2,1);
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
|
||||
bTimingOut = false;
|
||||
TimeInArea = 0.f;
|
||||
TimeOutOfArea = 0.f;
|
||||
}
|
||||
|
||||
function ConditionActivated(pawn ActivatingPlayer)
|
||||
{
|
||||
Super.ConditionActivated(ActivatingPlayer);
|
||||
|
||||
Duration = FMax(Duration,0.1f);
|
||||
|
||||
if(GetTargetActor(InitialAreaVolumeName) != none)
|
||||
{
|
||||
SetTargetActor(AreaVolumeName,GetTargetActor(InitialAreaVolumeName));
|
||||
}
|
||||
}
|
||||
|
||||
function ConditionTick(Float DeltaTime)
|
||||
{
|
||||
local controller AController;
|
||||
local Actor ProximityActor;
|
||||
local Volume MyAreaVolume;
|
||||
local int i;
|
||||
|
||||
NumInVolume = 0;
|
||||
|
||||
for(i = 0 ; i < PawnInstigatorNames.length ; i ++)
|
||||
{
|
||||
ReleaseTargetActor(PawnInstigatorNames[i]);
|
||||
}
|
||||
|
||||
PawnInstigatorNames.length = 0;
|
||||
|
||||
|
||||
MyAreaVolume = Volume(GetTargetActor(AreaVolumeName));
|
||||
if(MyAreaVolume != none || AreaZoneName != "" )
|
||||
{
|
||||
if(MyAreaVolume != none)
|
||||
{
|
||||
if(ClassIsChildOf(ProximityTriggerType,class 'Controller'))
|
||||
{
|
||||
for ( AController=GetObjOwner().Level.ControllerList; AController!=None; AController=AController.NextController )
|
||||
{
|
||||
if(AController.Pawn != none &&
|
||||
AController.Pawn.Health > 0 &&
|
||||
MyAreaVolume.Encompasses(AController.Pawn))
|
||||
{
|
||||
if(ClassIsChildOf(AController.class,ProximityTriggerType))
|
||||
{
|
||||
PawnInstigatorNames[PawnInstigatorNames.length] = AController.Pawn.name;
|
||||
SetTargetActor(AController.Pawn.name,AController.Pawn);
|
||||
NumInVolume ++ ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach MyAreaVolume.TouchingActors(class 'Actor', ProximityActor)
|
||||
{
|
||||
if(ProximityActor.IsA(ProximityTriggerType.name) &&
|
||||
!ProximityActor.bPendingDelete && (ProximityTag == '' ||
|
||||
ProximityActor.Tag == ProximityTag))
|
||||
{
|
||||
if(ProximityActor.Instigator != none)
|
||||
{
|
||||
PawnInstigatorNames[PawnInstigatorNames.length] = ProximityActor.Instigator.name;
|
||||
SetTargetActor(ProximityActor.Instigator.name,ProximityActor.Instigator);
|
||||
}
|
||||
|
||||
NumInVolume ++ ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(AreaZoneName != "")
|
||||
{
|
||||
for ( AController=GetObjOwner().Level.ControllerList; AController!=None; AController=AController.NextController )
|
||||
{
|
||||
if(AController.Pawn != none &&
|
||||
AController.Pawn.Health > 0 &&
|
||||
(ClassIsChildOf(AController.Pawn.Class,ProximityTriggerType) ||
|
||||
ClassIsChildOf(AController.Class,ProximityTriggerType)) &&
|
||||
(ProximityTag == '' || AController.Pawn.Tag == ProximityTag))
|
||||
{
|
||||
if(AController.Pawn.Region.Zone.LocationName == AreaZoneName)
|
||||
{
|
||||
PawnInstigatorNames[PawnInstigatorNames.length] = AController.Pawn.name;
|
||||
SetTargetActor(AController.Pawn.name,AController.Pawn);
|
||||
NumInVolume ++ ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(NumInVolume == 0 ||
|
||||
(bRequiresWholeTeam && NumInVolume < GetObjOwner().StoryGI.GetTotalActivePlayers()))
|
||||
{
|
||||
bTimingOut = true;
|
||||
|
||||
if(bKeepProgress)
|
||||
{
|
||||
TimeInArea = FMax( TimeInArea - DeltaTime, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeInArea = 0.f;
|
||||
}
|
||||
|
||||
TimeOutOfArea = FMin( TimeOutOfArea + DeltaTime, Duration );
|
||||
}
|
||||
else
|
||||
{
|
||||
bTimingOut = false;
|
||||
|
||||
TimeInArea = FMin( TimeInArea + DeltaTime, Duration );
|
||||
|
||||
if(bKeepProgress)
|
||||
{
|
||||
TimeOutOfArea = FMax( TimeOutOfArea - DeltaTime, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeOutOfArea = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Super.ConditionTick(DeltaTime);
|
||||
}
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
if(CompletionMethod == Method_LeaveArea)
|
||||
{
|
||||
return FClamp(TimeOutOfArea / Duration,0.f,1.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FClamp(TimeInArea / Duration,0.f,1.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function string GetDataString()
|
||||
{
|
||||
local string DataString;
|
||||
local int NumActivePlayers;
|
||||
|
||||
if(bRequiresWholeTeam )
|
||||
{
|
||||
NumActivePlayers = GetObjOwner().StoryGI.GetTotalActivePlayers() ;
|
||||
if(NumActivePlayers > 1)
|
||||
{
|
||||
DataString@="["$NumInVolume$"/"$NumActivePlayers$"]" ;
|
||||
}
|
||||
}
|
||||
|
||||
return DataString ;
|
||||
}
|
||||
|
||||
function string GetHUDHint()
|
||||
{
|
||||
local string HintString;
|
||||
|
||||
return Super.GetHUDHint();
|
||||
|
||||
|
||||
if( (CompletionMethod == Method_LeaveArea && bTimingOut) ||
|
||||
(CompletionMethod == Method_EnterArea && !bTimingOut) )
|
||||
{
|
||||
HintString = Super.GetHUDHint();
|
||||
}
|
||||
|
||||
return HintString ;
|
||||
}
|
||||
|
||||
function vector GetLocation(optional out Actor LocActor)
|
||||
{
|
||||
local Actor WorldLocActor;
|
||||
local Vector WorldLocation;
|
||||
local Volume MyAreaVolume;
|
||||
|
||||
if(ConditionIsActive())
|
||||
{
|
||||
MyAreaVolume = Volume(GetTargetActor(AreaVolumeName));
|
||||
|
||||
WorldLocation = Super.GetLocation(WorldLocActor);
|
||||
if(WorldLocActor != none)
|
||||
{
|
||||
LocActor = WorldLocActor;
|
||||
return WorldLocation;
|
||||
}
|
||||
|
||||
if(MyAreaVolume != none)
|
||||
{
|
||||
LocActor = MyAreaVolume;
|
||||
return LocActor.Location;
|
||||
}
|
||||
else
|
||||
if(AreaZoneName != "" && AssociatedZone != none)
|
||||
{
|
||||
LocActor = AssociatedZone;
|
||||
return LocActor.Location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
AreaVolumeName = "AreaVolume"
|
||||
InitialAreaVolumeName = "InitialAreaVolume"
|
||||
|
||||
CompletionMethod = Method_EnterArea
|
||||
ProximityTriggerType = class 'PlayerController'
|
||||
HUD_World=(bIgnoreWorldLocHidden=true)
|
||||
}
|
||||
123
kf_sources/KFStoryGame/Classes/ObjCondition_Counter.uc
Normal file
123
kf_sources/KFStoryGame/Classes/ObjCondition_Counter.uc
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Counter
|
||||
--------------------------------------------------------------
|
||||
|
||||
A Condition which increments each time its owning Objective is
|
||||
triggered.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_Counter extends KF_ObjectiveCondition
|
||||
editinlinenew;
|
||||
|
||||
enum ECounterType
|
||||
{
|
||||
CT_Default, // default setting - NumToCount is user defined and NumCounted represents the number of times this objective has been triggered .
|
||||
CT_Cash, // NumCounted becomes the total cash sum accrued by all players. NumToCount is whatever sum of cash you expect them to accumulate.
|
||||
CT_PlayerCount, // NumCounted becomes the number of unique players who triggered this Objective. NumToCount is the total number of active players in the match.
|
||||
};
|
||||
|
||||
|
||||
var () ECounterType CountType;
|
||||
|
||||
var () int NumToCount;
|
||||
|
||||
var int NumCounted,SavedNumCounted;
|
||||
|
||||
/* if SuccessCondition is set to OBJ_Counter and CountType is CT_PlayerCount, this array will store unique player IDs for each
|
||||
played who has been 'counted' so far. */
|
||||
var array<int> CountedPlayerIDs;
|
||||
|
||||
|
||||
function SaveState()
|
||||
{
|
||||
Super.SaveState();
|
||||
SavedNumCounted = NumCounted;
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
NumCounted = SavedNumCounted;
|
||||
CountedPlayerIDs.length = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
local float Numerator;
|
||||
local float Denominator;
|
||||
|
||||
switch(CountType)
|
||||
{
|
||||
case CT_Default : break;
|
||||
case CT_Cash : NumCounted = GetObjOwner().StoryGI.GetTotalCashSum(); break;
|
||||
case CT_PlayerCount : NumToCount = Max(GetObjOwner().StoryGI.GetTotalActivePlayers(),1); break;
|
||||
}
|
||||
|
||||
Numerator = float(NumCounted);
|
||||
// Take the floor of the modified amount to ensure accuracy. Also, there's no floor function available.
|
||||
Denominator = float(int(float(NumToCount) * GetTotalDifficultyModifier()));
|
||||
return FClamp(Numerator/Denominator,0.f,1.f) ;
|
||||
}
|
||||
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator)
|
||||
{
|
||||
Super.Trigger(Other,EventInstigator);
|
||||
|
||||
/* each trigger increments the 'counter' for objectives of that type */
|
||||
if(ConditionIsActive() && ValidForCounting(EventInstigator))
|
||||
{
|
||||
SetTargetActor(InstigatorName,EventInstigator);
|
||||
NumCounted = Min(NumCounted + 1,Round(NumToCount * GetTotalDifficultyModifier())) ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Relevant if this Objective is configured to count players -
|
||||
returns true if this is the first time the supplied pawn has triggered us
|
||||
*/
|
||||
|
||||
function bool ValidForCounting(Pawn CountedPawn)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(CountType == CT_PlayerCount &&
|
||||
CountedPawn.PlayerReplicationInfo != none)
|
||||
{
|
||||
for( i = 0 ; i < CountedPlayerIDs.length ; i ++)
|
||||
{
|
||||
/* this guy has already been counted. ignore him */
|
||||
if(CountedPlayerIDs[i] == CountedPawn.PlayerReplicationInfo.PlayerID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got this far CountedPawn is unique - add his ID to the array */
|
||||
CountedPlayerIDs[CountedPlayerIDs.length] = CountedPawn.PlayerReplicationInfo.PlayerID ;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function string GetDataString()
|
||||
{
|
||||
if(HUD_Screen.Screen_CountStyle < 1)
|
||||
{
|
||||
return NumCounted$"/"$int(NumToCount * GetTotalDifficultyModifier()) ;
|
||||
}
|
||||
|
||||
return string(Max((int(NumToCount * GetTotalDifficultyModifier()))-NumCounted,0)) ;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
NumToCount = 1
|
||||
}
|
||||
68
kf_sources/KFStoryGame/Classes/ObjCondition_Inventory.uc
Normal file
68
kf_sources/KFStoryGame/Classes/ObjCondition_Inventory.uc
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Inventory
|
||||
--------------------------------------------------------------
|
||||
|
||||
A Condition which is marked complete when a player is carrying
|
||||
an inventory item of the specified class.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_Inventory extends KF_ObjectiveCondition
|
||||
editinlinenew;
|
||||
|
||||
/* The type of inventory item to search for */
|
||||
var() class<Inventory> DesiredItemClass;
|
||||
|
||||
var bool bHeld;
|
||||
|
||||
var() name DesiredItemTag;
|
||||
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
bHeld = false;
|
||||
}
|
||||
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
return float(bHeld && AllowCompletion());
|
||||
}
|
||||
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
local Controller C;
|
||||
local Inventory Inv;
|
||||
|
||||
Super.ConditionTick(DeltaTime);
|
||||
|
||||
bHeld = false;
|
||||
|
||||
for ( C=GetObjOwner().Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if(PlayerController(C) != none && C.Pawn != none)
|
||||
{
|
||||
for( Inv = C.Pawn.Inventory; Inv != None ; Inv = Inv.Inventory )
|
||||
{
|
||||
if(ClassIsChildOf(Inv.class,DesiredItemClass) && (DesiredItemTag == '' ||
|
||||
Inv.tag == DesiredItemTag))
|
||||
{
|
||||
bHeld = true;
|
||||
SetTargetActor(InstigatorName,C.Pawn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
HUD_Screen=(Screen_ProgressStyle=HDS_TextOnly)
|
||||
}
|
||||
68
kf_sources/KFStoryGame/Classes/ObjCondition_LineOfSight.uc
Normal file
68
kf_sources/KFStoryGame/Classes/ObjCondition_LineOfSight.uc
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_LineOfSight
|
||||
--------------------------------------------------------------
|
||||
|
||||
A Condition which is marked complete when a living human player
|
||||
looks at / has an unobstructed line of sight to it.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_LineOfSight extends KF_ObjectiveCondition
|
||||
editinlinenew;
|
||||
|
||||
var () float MinDotProduct;
|
||||
var () float MinDistance;
|
||||
var () bool bPerformLineCheck;
|
||||
|
||||
var bool bHasLOS;
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
bHasLOS = false;
|
||||
}
|
||||
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
local Controller C;
|
||||
local float Dist;
|
||||
|
||||
for ( C=GetObjOwner().Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if(KFPlayerController_Story(C) != none && C.Pawn != none)
|
||||
{
|
||||
if(KFPlayerController_Story(C).IsLookingAtLocation(GetLocation(),MinDotProduct) && C.Pawn != none)
|
||||
{
|
||||
Dist = VSize(C.Pawn.Location - GetLocation());
|
||||
if( Dist <= MinDistance)
|
||||
{
|
||||
bHasLOS = (!bPerformLineCheck || GetObjOwner().FastTrace(PlayerController(C).CalcViewLocation, GetLocation())); //EyePostion() is returning a funny value sometimes. Not sure why. C.Pawn./*EyePosition()*/Location
|
||||
if(bHasLOS)
|
||||
{
|
||||
SetTargetActor(InstigatorName,C.Pawn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Super.ConditionTick(DeltaTime);
|
||||
}
|
||||
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
return float(bHasLOS) ;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
bPerformLineCheck=true
|
||||
MinDistance = 1000
|
||||
}
|
||||
85
kf_sources/KFStoryGame/Classes/ObjCondition_Multi.uc
Normal file
85
kf_sources/KFStoryGame/Classes/ObjCondition_Multi.uc
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Multi
|
||||
--------------------------------------------------------------
|
||||
|
||||
Multi Conditions are marked complete only when all 'child'
|
||||
conditions are also Complete
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class ObjCondition_Multi extends KF_ObjectiveCondition
|
||||
editinlinenew;
|
||||
|
||||
var () array<KF_ObjectiveCondition> ChildConditions;
|
||||
|
||||
var array<byte> CompleteConditions;
|
||||
|
||||
var int NumCompleted,NumConditions;
|
||||
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
local int i;
|
||||
local array<KF_ObjectiveCondition> ValidConditions;
|
||||
|
||||
NumConditions = 0;
|
||||
|
||||
for(i = 0 ; i < ChildConditions.length ; i ++)
|
||||
{
|
||||
if(ChildConditions[i].ConditionIsRelevant())
|
||||
{
|
||||
ValidConditions[ValidConditions.length] = ChildConditions[i];
|
||||
}
|
||||
}
|
||||
|
||||
NumConditions = ValidConditions.length;
|
||||
CompleteConditions.length = ValidConditions.length;
|
||||
|
||||
for(i = 0 ; i < ValidConditions.length ; i ++)
|
||||
{
|
||||
if(ValidConditions[i].bComplete)
|
||||
{
|
||||
CompleteConditions[i] = 1 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
CompleteConditions[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NumCompleted = 0;
|
||||
for(i = 0 ; i < NumConditions ; i ++)
|
||||
{
|
||||
if(CompleteConditions[i] == 1)
|
||||
{
|
||||
NumCompleted ++ ;
|
||||
}
|
||||
}
|
||||
|
||||
Super.ConditionTick(DeltaTime);
|
||||
}
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
return float(NumCompleted) / float(NumConditions) ;
|
||||
}
|
||||
|
||||
function string GetDataString()
|
||||
{
|
||||
if(HUD_Screen.Screen_CountStyle < 1)
|
||||
{
|
||||
return NumCompleted$"/"$NumConditions ;
|
||||
}
|
||||
|
||||
return string(Max(NumConditions-NumCompleted,0)) ;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
bForceReliableUpdate=true
|
||||
}
|
||||
109
kf_sources/KFStoryGame/Classes/ObjCondition_Random.uc
Normal file
109
kf_sources/KFStoryGame/Classes/ObjCondition_Random.uc
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Random
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Condition serves as a container for any number of other Conditions.
|
||||
when initalized, it picks one at random and activates it.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_Random extends KF_ObjectiveCondition
|
||||
hidecategories(Difficulty,HUD,Events,KF_ObjectiveCondition)
|
||||
editinlinenew;
|
||||
|
||||
var int RandIdx;
|
||||
|
||||
struct SRandomCondition
|
||||
{
|
||||
var () editinlineuse KF_ObjectiveCondition Condition;
|
||||
|
||||
var () int Priority;
|
||||
};
|
||||
|
||||
var int ConditionIndex;
|
||||
|
||||
var (Conditions) float PriorityBias;
|
||||
|
||||
var (Conditions) editinlineuse array<SRandomCondition> RandomConditions;
|
||||
|
||||
|
||||
|
||||
function ConditionActivated(pawn ActivatingPlayer)
|
||||
{
|
||||
Super.ConditionActivated(ActivatingPlayer);
|
||||
ConditionIndex = GetObjOwner().FindIndexForCondition(self);
|
||||
AssignRandomCondition();
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
super.Reset();
|
||||
SwapConditionAtIndex(ConditionType,self);
|
||||
}
|
||||
|
||||
function AssignRandomCondition()
|
||||
{
|
||||
local float HighestRating;
|
||||
local float PriorityVal;
|
||||
local int BestIdx;
|
||||
local array<float> Ratings;
|
||||
local int i,idx;
|
||||
|
||||
HighestRating = -1;
|
||||
|
||||
for(i = 0 ; i < RandomConditions.length ; i ++)
|
||||
{
|
||||
if(!RandomConditions[i].Condition.bComplete)
|
||||
{
|
||||
PriorityVal = RandomConditions[i].Priority ;
|
||||
Ratings[i] = RandRange( FMin(Ratings[idx] * PriorityBias,Ratings[idx]) , PriorityVal ) ;
|
||||
}
|
||||
}
|
||||
|
||||
for(idx = 0 ; idx < Ratings.length ; idx ++)
|
||||
{
|
||||
if(Ratings[idx] > highestRating )
|
||||
{
|
||||
BestIdx = idx;
|
||||
HighestRating = Ratings[idx] ;
|
||||
}
|
||||
}
|
||||
|
||||
if(BestIdx < 0 || BestIdx >= RandomConditions.length)
|
||||
{
|
||||
log("Warning - Cannot find a valid Condition for : "@self@" Random Condition will fail. ",'Story_Debug');
|
||||
}
|
||||
|
||||
RandIdx = BestIdx;
|
||||
|
||||
RandomConditions[RandIdx].Condition.ConditionType = ConditionType;
|
||||
RandomConditions[RandIdx].Condition.SetObjOwner(GetObjOwner());
|
||||
|
||||
if(RandomConditions[RandIdx].Condition.ShouldInitOnActivation())
|
||||
{
|
||||
GetObjOwner().ActivateCondition(RandomConditions[RandIdx].Condition);
|
||||
|
||||
}
|
||||
|
||||
SwapConditionAtIndex(ConditionIndex,RandomConditions[RandIdx].Condition) ;
|
||||
}
|
||||
|
||||
function SwapConditionAtIndex(int Index, KF_ObjectiveCondition SwapCondition)
|
||||
{
|
||||
switch(ConditionType)
|
||||
{
|
||||
case 0 : GetObjOwner().FailureConditions[Index] = SwapCondition; break;
|
||||
case 1 : GetObjOwner().SuccessConditions[Index] = SwapCondition; break;
|
||||
case 2 : GetObjOwner().OptionalConditions[Index] = SwapCondition; break;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
PriorityBias = 0.5
|
||||
HUD_Screen=(Screen_ProgressStyle=HDS_TextOnly)
|
||||
}
|
||||
80
kf_sources/KFStoryGame/Classes/ObjCondition_Timed.uc
Normal file
80
kf_sources/KFStoryGame/Classes/ObjCondition_Timed.uc
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Timed
|
||||
--------------------------------------------------------------
|
||||
|
||||
A Condition which is marked complete after a specified amount of
|
||||
time expires.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_Timed extends KF_ObjectiveCondition
|
||||
editinlinenew;
|
||||
|
||||
var bool bTraderTime;
|
||||
|
||||
var () float Duration;
|
||||
|
||||
var float RemainingSeconds;
|
||||
|
||||
var float StartTime;
|
||||
|
||||
function AdjustToDifficulty(float Difficulty)
|
||||
{
|
||||
Duration /= FMax(Difficulty-2,1);
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
StartTime = 0.f;
|
||||
RemainingSeconds = Duration;
|
||||
}
|
||||
|
||||
function ConditionActivated(pawn ActivatingPlayer)
|
||||
{
|
||||
Super.ConditionActivated(ActivatingPlayer);
|
||||
// log("======================"@self@"was just activated by : "@ActivatingPlayer,'Story_Debug');
|
||||
RemainingSeconds = Duration ;
|
||||
StartTime = GetObjOwner().Level.TimeSeconds ;
|
||||
}
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
return FClamp(1.f- (RemainingSeconds / Duration),0.f,1.f);
|
||||
}
|
||||
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
local float NewTimeRemaining;
|
||||
|
||||
if(RemainingSeconds > 0)
|
||||
{
|
||||
NewTimeRemaining = FMax(Duration - int(GetObjOwner().Level.TimeSeconds - StartTime),0) ;
|
||||
RemainingSeconds = NewTimeRemaining;
|
||||
}
|
||||
|
||||
Super.ConditionTick(DeltaTime);
|
||||
}
|
||||
|
||||
function string GetDataString()
|
||||
{
|
||||
if(HUD_Screen.Screen_CountStyle == Count_Down)
|
||||
{
|
||||
return FormatTime(RemainingSeconds) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FormatTime(GetObjOwner().Level.TimeSeconds - StartTime) ;
|
||||
}
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
Duration = 60.f
|
||||
HUD_Screen=(Screen_Hint="Time Left :",Screen_ProgressStyle=HDS_TextOnly,Screen_CountStyle=Count_Down)
|
||||
}
|
||||
29
kf_sources/KFStoryGame/Classes/ObjCondition_Touch.uc
Normal file
29
kf_sources/KFStoryGame/Classes/ObjCondition_Touch.uc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Touch
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Condition is marked complete when a player encroaches the
|
||||
collision cylinder of its owning Objective actor.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_Touch extends KF_ObjectiveCondition
|
||||
hidecategories(Difficulty)
|
||||
editinlinenew;
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
return float(GetObjOwner().bWasTouched) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
|
||||
}
|
||||
114
kf_sources/KFStoryGame/Classes/ObjCondition_TraderTime.uc
Normal file
114
kf_sources/KFStoryGame/Classes/ObjCondition_TraderTime.uc
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_TraderShop
|
||||
--------------------------------------------------------------
|
||||
|
||||
A Type of timed condition which displays HUD info for Trader shops.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_TraderTime extends ObjCondition_Timed
|
||||
editinlinenew;
|
||||
|
||||
var bool OldShopOpen;
|
||||
|
||||
/* Point the whisp at the pathnode closest to the Entrance to the trader shop*/
|
||||
|
||||
function vector GetWhispLocation(optional out Actor LocActor)
|
||||
{
|
||||
LocActor = GetNearestPathNodeTo(GetAssociatedDoor().Location);
|
||||
return LocActor.Location;
|
||||
}
|
||||
|
||||
function bool ShouldShowWhispTrailFor(PlayerController C)
|
||||
{
|
||||
return Super.ShouldShowWhispTrailFor(C) && (KFPlayerController(C) == none || KFPlayerController(C).bWantsTraderPath) ;
|
||||
}
|
||||
|
||||
/* Retrieves the Trader Door associated with the Currently Active Shop */
|
||||
function KFTraderDoor GetAssociatedDoor()
|
||||
{
|
||||
local int i;
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
KFGRI = KFGameReplicationInfo(GetObjOwner().Level.game.GameReplicationInfo) ;
|
||||
if(GetObjOwner().StoryGI == none || KFGRI == none || KFGRI.CurrentShop == none)
|
||||
{
|
||||
return none;
|
||||
}
|
||||
|
||||
for(i = 0 ; i < GetObjOwner().StoryGI.AllTraderDoors.length ; i ++)
|
||||
{
|
||||
if(GetObjOwner().StoryGI.AllTraderDoors[i].Tag == KFGRI.CurrentShop.Event)
|
||||
{
|
||||
return GetObjOwner().StoryGI.AllTraderDoors[i];
|
||||
}
|
||||
}
|
||||
|
||||
return none;
|
||||
}
|
||||
|
||||
/*Center the icon on the ShopVolume */
|
||||
|
||||
function vector GetLocation(optional out Actor LocActor)
|
||||
{
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
if(ConditionIsActive())
|
||||
{
|
||||
KFGRI = KFGameReplicationInfo(GetObjOwner().Level.game.GameReplicationInfo) ;
|
||||
if(KFGRI != none && KFGRI.CurrentShop != none)
|
||||
{
|
||||
LocActor = KFGRI.CurrentShop;
|
||||
return KFGRI.CurrentShop.Location ;
|
||||
}
|
||||
}
|
||||
|
||||
return vect(0,0,0);
|
||||
}
|
||||
|
||||
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
Super.ConditionTick(DeltaTime);
|
||||
UpdateWhispVisibility();
|
||||
}
|
||||
|
||||
function ConditionDeActivated()
|
||||
{
|
||||
Super.ConditionDeActivated();
|
||||
UpdateWhispVisibility();
|
||||
}
|
||||
|
||||
function UpdateWhispVisibility()
|
||||
{
|
||||
local bool NewShopOpen;
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
KFGRI = KFGameReplicationInfo(GetObjOwner().Level.Game.GameReplicationInfo);
|
||||
if(KFGRI == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(KFGRI.CurrentShop != none)
|
||||
{
|
||||
NewShopOpen = KFGRI.CurrentShop.bCurrentlyOpen;
|
||||
|
||||
// only show a whisp trail when the shop is open for business
|
||||
HUD_World.bShowWhispTrail = NewShopOpen ;
|
||||
|
||||
OldShopOpen = NewShopOpen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
bTraderTime = true
|
||||
HUD_World=(bHide=false,bShowWhispTrail=true,World_Hint="Trader",World_Texture=Texture 'KFStoryGame_Tex.HUD.Trader_Icon_64',bIgnoreWorldLocHidden=true)
|
||||
}
|
||||
|
||||
28
kf_sources/KFStoryGame/Classes/ObjCondition_Triggered.uc
Normal file
28
kf_sources/KFStoryGame/Classes/ObjCondition_Triggered.uc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Triggered
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Condition is marked complete when its owning objective is
|
||||
the recipient of a trigger event
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_Triggered extends KF_ObjectiveCondition
|
||||
hidecategories(Difficulty)
|
||||
editinlinenew;
|
||||
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
return float(bWasTriggered);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
HUD_Screen=(Screen_ProgressStyle=HDS_TextOnly)
|
||||
}
|
||||
326
kf_sources/KFStoryGame/Classes/ObjCondition_Use.uc
Normal file
326
kf_sources/KFStoryGame/Classes/ObjCondition_Use.uc
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Condition_Use
|
||||
--------------------------------------------------------------
|
||||
|
||||
This Condition is marked complete when a player presses the 'Use'
|
||||
key while in range of its owning actor.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class ObjCondition_Use extends KF_ObjectiveCondition
|
||||
editinlinenew;
|
||||
|
||||
/* requires that line of sight be maintained with the objective during the use process. Only really relevant if HoldUseSeconds is something > 0 */
|
||||
var () bool bMaintainUseLOS;
|
||||
/* Min View angle cosine required to perform a 'use' action */
|
||||
var () float MinUseViewAngle;
|
||||
/* Number of seconds a player must hold the use key for before the objective completes. Releasing the key will abort any progress. */
|
||||
var () float HoldUseSeconds;
|
||||
/* if true, any progress made 'Using' this objective will be kept if the player stops holding the use key. only relevant if HoldUseSeconds is > 0 */
|
||||
var () bool bKeepUseProgress;
|
||||
|
||||
var () name UsePawn_Tag;
|
||||
|
||||
var float FinishedUseSeconds;
|
||||
|
||||
var float LastUseTime;
|
||||
|
||||
var bool bAcquiredPawn;
|
||||
|
||||
var bool bWasUsed;
|
||||
|
||||
var const name UseActorName,InitialUseActorName,CurrentUserName,ControlledMoverName;
|
||||
|
||||
var () edfindable private Actor UseActor; // this exists only for level designers.
|
||||
|
||||
|
||||
function Reset()
|
||||
{
|
||||
Super.Reset();
|
||||
FinishedUseSeconds = 0.f;
|
||||
bWasUsed = false;
|
||||
}
|
||||
|
||||
function PostBeginPlay(KF_StoryObjective MyOwner)
|
||||
{
|
||||
Super.PostBeginPlay(MyOwner);
|
||||
|
||||
// Ditch any reference to this actor ASAP.
|
||||
if(UseActor != none)
|
||||
{
|
||||
SetTargetActor(InitialUseActorName,UseActor);
|
||||
SetTargetActor(UseActorName,UseActor);
|
||||
UseActor = none;
|
||||
}
|
||||
}
|
||||
|
||||
function SetObjOwner(KF_StoryObjective NewOwner)
|
||||
{
|
||||
local Actor MyUseActor;
|
||||
|
||||
MyUseActor = GetTargetActor(UseActorName);
|
||||
if(MyUseActor == none || (NewOwner != MyUseActor && GetObjOwner() == MyUseActor))
|
||||
{
|
||||
SetTargetActor(UseActorName,NewOwner);
|
||||
}
|
||||
|
||||
Super.SetObjOwner(NewOwner);
|
||||
}
|
||||
|
||||
function ConditionActivated(pawn ActivatingPlayer)
|
||||
{
|
||||
local Actor InitialUseActor,MyUseActor;
|
||||
local KF_UseableMover ControlledMover;
|
||||
|
||||
Super.ConditionActivated(ActivatingPlayer);
|
||||
|
||||
InitialUseActor = GetTargetActor(InitialUseActorName);
|
||||
MyUseActor = GetTargetActor(UseActorName);
|
||||
|
||||
if(InitialuseActor != none &&
|
||||
!InitialuseActor.bPendingDelete)
|
||||
{
|
||||
SetTargetActor('UseActorName',InitialUseActor);
|
||||
if(KF_UseableMover(MyUseActor) != none)
|
||||
{
|
||||
SetTargetActor(ControlledMoverName,KF_UseableMover(MyUseActor));
|
||||
ControlledMover = KF_UseableMover(GetTargetActor(ControlledMoverName));
|
||||
if(ControlledMover != none)
|
||||
{
|
||||
ControlledMover.Notify_Controlled(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
local float RemainingHoldUseTime;
|
||||
local Actor MyUseActor;
|
||||
local Pawn CurrentUser;
|
||||
|
||||
UpdateUseablePawnList();
|
||||
|
||||
MyUseActor = GetTargetActor(UseActorName);
|
||||
CurrentUser = Pawn(GetTargetActor(CurrentUserName));
|
||||
|
||||
/* Important we call this before the Range checks or it won't register completion */
|
||||
Super.ConditionTick(DeltaTime);
|
||||
|
||||
if(CurrentUser != none && CurrentUser.Controller != none)
|
||||
{
|
||||
RemainingHoldUseTime = GetRemainingUseTime() ;
|
||||
if(!InRangeAndView() || RemainingHoldUseTime <= 0)
|
||||
{
|
||||
StopUsingObj(CurrentUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function UpdateUseablePawnList()
|
||||
{
|
||||
local Controller C;
|
||||
local Actor MyUseActor;
|
||||
|
||||
MyUseActor = GetTargetActor(UseActorName);
|
||||
|
||||
if(UsePawn_Tag == '' ||
|
||||
(MyUseActor != none &&
|
||||
MyUseActor.Tag == UsePawn_Tag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( C= GetObjOwner().Level.ControllerList; C!=None; C=C.NextController )
|
||||
{
|
||||
if(C.Pawn != none &&
|
||||
!C.Pawn.bDeleteMe &&
|
||||
!C.Pawn.bPendingDelete &&
|
||||
C.Pawn.Health > 0 &&
|
||||
C.Pawn.Tag == UsePawn_Tag)
|
||||
{
|
||||
SetTargetActor(UseActorName,C.Pawn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bool InRangeAndView()
|
||||
{
|
||||
local bool bhasLOS;
|
||||
local bool bInRange;
|
||||
local Pawn CurrentUser;
|
||||
|
||||
CurrentUser = Pawn(GetTargetActor(CurrentUserName));
|
||||
|
||||
if(CurrentUser == none)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bHasLOS = (!bMaintainUseLOS ||
|
||||
KFPlayerController_Story(CurrentUser.Controller) != none &&
|
||||
KFPlayerController_Story(CurrentUser.Controller).IsLookingAtLocation(GetLocation(),MinUseViewAngle));
|
||||
|
||||
bInRange = IsTouchingUseActor(CurrentUser) ;
|
||||
|
||||
return bInRange && bHasLOS;
|
||||
}
|
||||
|
||||
function bool IsTouchingUseActor(pawn Toucher)
|
||||
{
|
||||
local Actor A;
|
||||
local float DistSq;
|
||||
local Actor MyUseActor;
|
||||
|
||||
MyUseActor = GetTargetActor(UseActorName);
|
||||
|
||||
if(Toucher != none && MyUseActor != none)
|
||||
{
|
||||
foreach Toucher.TouchingActors(class 'Actor', A)
|
||||
{
|
||||
if(A == MyUseActor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(MyUseActor.bBlockActors)
|
||||
{
|
||||
DistSq = VsizeSquared(MyUseActor.Location - Toucher.Location) ;
|
||||
if(DistSq <= Square( (MyUseActor.CollisionRadius + (Toucher.CollisionRadius)) * 1.25 ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function Startedusing(pawn User)
|
||||
{
|
||||
local Pawn CurrentUser;
|
||||
local KF_UseableMover ControlledMover;
|
||||
|
||||
ControlledMover = KF_UseableMover(GetTargetActor(ControlledMoverName));
|
||||
CurrentUser = Pawn(GetTargetActor(CurrentUserName));
|
||||
|
||||
if(CurrentUser == none && IsTouchingUseActor(User))
|
||||
{
|
||||
SetTargetActor(InstigatorName,User);
|
||||
SetTargetActor(CurrentUserName,User);
|
||||
LastUseTime = User.Level.TimeSeconds;
|
||||
|
||||
if(AllowCompletion())
|
||||
{
|
||||
bWasUsed = true;
|
||||
}
|
||||
|
||||
if(ControlledMover != none)
|
||||
{
|
||||
ControlledMover.StartedUsing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function StoppedUsing(pawn User)
|
||||
{
|
||||
local KF_UseableMover ControlledMover;
|
||||
|
||||
ControlledMover = KF_USeableMover(GetTargetActor(ControlledMoverName));
|
||||
|
||||
StopusingObj(User);
|
||||
if(ControlledMover != none)
|
||||
{
|
||||
ControlledMover.StoppedUsing();
|
||||
}
|
||||
}
|
||||
|
||||
function StopUsingObj(pawn User)
|
||||
{
|
||||
local Pawn CurrentUser;
|
||||
|
||||
CurrentUser = Pawn(GetTargetActor(CurrentUserName));
|
||||
if(CurrentUser != none &&
|
||||
User == CurrentUser)
|
||||
{
|
||||
/* Cache the amount of time we have been holding use for */
|
||||
if( bKeepUseProgress)
|
||||
{
|
||||
FinishedUseSeconds += (User.Level.TimeSeconds - LastUseTime) ;
|
||||
}
|
||||
|
||||
SetTargetActor(CurrentUserName,none);
|
||||
}
|
||||
}
|
||||
|
||||
function vector GetLocation(optional out actor LocActor)
|
||||
{
|
||||
local Actor MyUseActor;
|
||||
|
||||
if(ConditionIsActive())
|
||||
{
|
||||
MyUseActor = GetTargetActor(UseActorName);
|
||||
|
||||
if(MyUseActor != none &&
|
||||
!MyUseActor.bPendingDelete)
|
||||
{
|
||||
LocActor = MyUseActor;
|
||||
return MyUseActor.Location;
|
||||
}
|
||||
|
||||
return Super.GetLocation(LocActor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
if(HoldUseSeconds > 0)
|
||||
{
|
||||
return 1.f - (GetRemainingUseTime() / HoldUseSeconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
return float(bWasUsed);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wrapper for finding the amount of time a player needs to hold down the USE key to complete this condition */
|
||||
function float GetRemainingUseTime()
|
||||
{
|
||||
local Pawn CurrentUser;
|
||||
|
||||
CurrentUser = Pawn(GetTargetActor(CurrentUserName));
|
||||
if(CurrentUser != none)
|
||||
{
|
||||
return FMax(HoldUseSeconds - ((GetObjOwner().Level.TimeSeconds - LastUseTime) + FinishedUseSeconds), 0.f) ;
|
||||
}
|
||||
|
||||
return (HoldUseSeconds - FinishedUseSeconds);
|
||||
}
|
||||
|
||||
function string GetDataString()
|
||||
{
|
||||
if(HoldUseSeconds > 0)
|
||||
{
|
||||
return Round((1.f-(GetRemainingUseTime() / HoldUseSeconds))*100.f)$"%" ;
|
||||
}
|
||||
|
||||
return "" ;
|
||||
}
|
||||
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
UseActorName = "UseActor"
|
||||
InitialUseActorName = "InitialUseActor"
|
||||
CurrentUserName = "CurrentUser"
|
||||
ControlledMoverName = "ControlledMover"
|
||||
}
|
||||
145
kf_sources/KFStoryGame/Classes/ObjCondition_WaveCounter.uc
Normal file
145
kf_sources/KFStoryGame/Classes/ObjCondition_WaveCounter.uc
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
//-----------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
class ObjCondition_WaveCounter extends ObjCondition_Counter
|
||||
hidecategories(ObjCondition_Counter);
|
||||
|
||||
var const name WaveDesignerName;
|
||||
|
||||
var int LastWaveIdx;
|
||||
|
||||
/* Tag of the WaveDesigner tied to this wave counter */
|
||||
var() name DesignerTag;
|
||||
|
||||
var() bool bUseCurrentWave;
|
||||
|
||||
var() int AssociatedWaveIndex;
|
||||
|
||||
var() int AssociatedCycleIndex;
|
||||
|
||||
var() bool bSumOfAllCycles;
|
||||
|
||||
var int NumStragglers;
|
||||
|
||||
function ConditionActivated(pawn ActivatingPlayer)
|
||||
{
|
||||
local KF_StoryWaveDesigner WaveDesigner;
|
||||
|
||||
NumCounted = 0;
|
||||
Super.ConditionActivated(ActivatingPlayer);
|
||||
|
||||
foreach GetObjOwner().AllActors(class 'KF_StoryWaveDesigner' , WaveDesigner,DesignerTag)
|
||||
{
|
||||
SetTargetActor(WaveDesignerName,WaveDesigner);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function ConditionDeActivated()
|
||||
{
|
||||
super.ConditionDeActivated();
|
||||
// let's actually let the objective control this stuff manually ...
|
||||
// WaveDesigner.Waves[GetAssociatedWaveIndex()].WaveController.AbortWave();
|
||||
}
|
||||
|
||||
/* returns the percentage of completion for this condition */
|
||||
function float GetCompletionPct()
|
||||
{
|
||||
local KF_StoryWaveDesigner WaveDesigner;
|
||||
|
||||
WaveDesigner = KF_StoryWaveDesigner(GetTargetActor(WaveDesignername));
|
||||
if(WaveDesigner == none)
|
||||
{
|
||||
// log("WARNING - no Wave Designer associated with : "@name,'Story_Debug');
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
if(WaveDesigner.Waves[GetAssociatedWaveIndex()].WaveController.bActive)
|
||||
{
|
||||
if(bSumOfAllCycles)
|
||||
{
|
||||
NumToCount = WaveDesigner.Waves[GetAssociatedWaveIndex()].WaveController.GetMaxMonsters();
|
||||
}
|
||||
else
|
||||
{
|
||||
NumToCount = WaveDesigner.Waves[GetAssociatedWaveIndex()].WaveController.GetCycleMaxZEDs(AssociatedCycleIndex) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumToCount = WaveDesigner.Waves[GetAssociatedWaveIndex()].WaveController.NumStragglers;
|
||||
|
||||
NumCounted = NumToCount - GetObjOwner().StoryGI.NumMonsters;
|
||||
}
|
||||
|
||||
/* NO ZEDS . Complete automatically */
|
||||
if(NumToCount <= 0)
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
return Super.GetCompletionPct();
|
||||
}
|
||||
|
||||
function int GetAssociatedWaveIndex()
|
||||
{
|
||||
local int WaveIdx;
|
||||
|
||||
if(bUseCurrentWave)
|
||||
{
|
||||
WaveIdx = KF_StoryWaveDesigner(GetTargetActor(WaveDesignername)).CurrentWaveIdx ;
|
||||
}
|
||||
else
|
||||
{
|
||||
WaveIdx = AssociatedWaveIndex;
|
||||
}
|
||||
|
||||
return WaveIdx;
|
||||
}
|
||||
|
||||
/* We need to ensure that the counter is reset between waves */
|
||||
function ConditionTick(float DeltaTime)
|
||||
{
|
||||
local int NewWaveIdx;
|
||||
local KF_StoryWaveDesigner WaveDesigner;
|
||||
|
||||
Super.ConditionTick(DeltaTime);
|
||||
|
||||
WaveDesigner = KF_StoryWaveDesigner(GetTargetActor(WaveDesignername));
|
||||
if(WaveDesigner != none)
|
||||
{
|
||||
NewWaveIdx = GetAssociatedWaveIndex();
|
||||
|
||||
if(NewWaveIdx != LastWaveIdx)
|
||||
{
|
||||
OnWaveChange();
|
||||
}
|
||||
|
||||
LastWaveIdx = NewWaveIdx;
|
||||
}
|
||||
}
|
||||
|
||||
function OnWaveChange()
|
||||
{
|
||||
NumCounted = 0;
|
||||
}
|
||||
|
||||
function Trigger( actor Other, pawn EventInstigator)
|
||||
{
|
||||
Super.Trigger(Other,EventInstigator);
|
||||
// log("You have killed : "@NumCounted@"ZEDS out of : "@NumToCount,'Story_Debug');
|
||||
}
|
||||
|
||||
/* Difficulty scaling for enemies is handled in the Wave Controller, so don't do it twice. */
|
||||
function float GetTotalDifficultyModifier()
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
WaveDesignerName = "WaveDesigner"
|
||||
CountType = CT_Default
|
||||
bUseCurrentWave = true
|
||||
bSumOfAllCycles = true
|
||||
}
|
||||
53
kf_sources/KFStoryGame/Classes/Objective_Whisp.uc
Normal file
53
kf_sources/KFStoryGame/Classes/Objective_Whisp.uc
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
class Objective_Whisp extends RedWhisp;
|
||||
|
||||
var transient vector DestLoc;
|
||||
|
||||
|
||||
function PostBeginPlay()
|
||||
{
|
||||
super(xEmitter).PostBeginPlay();
|
||||
InitWhisp();
|
||||
}
|
||||
|
||||
function InitWhisp()
|
||||
{
|
||||
local int i,start;
|
||||
local PlayerController C;
|
||||
local Actor HitActor;
|
||||
local Vector HitLocation,HitNormal;
|
||||
|
||||
|
||||
C = PlayerController(Owner);
|
||||
if ( C.Pawn == None )
|
||||
return;
|
||||
SetLocation(C.Pawn.Location);
|
||||
|
||||
WayPoints[0] = C.Pawn.Location + 200 * vector(C.Rotation);
|
||||
HitActor = Trace(HitLocation, HitNormal,WayPoints[0], C.Pawn.Location,false);
|
||||
if ( HitActor != None )
|
||||
WayPoints[0] = HitLocation;
|
||||
NumPoints++;
|
||||
|
||||
if ( (C.RouteCache[i] != None) && C.RouteCache[1] != none && C.ActorReachable(C.RouteCache[1]) )
|
||||
start = 1;
|
||||
for ( i=start; i<start+10; i++ )
|
||||
{
|
||||
if ( C.RouteCache[i] == None )
|
||||
break;
|
||||
else
|
||||
{
|
||||
WayPoints[NumPoints] = C.RouteCache[i].Location;
|
||||
NumPoints++;
|
||||
}
|
||||
}
|
||||
|
||||
if( NumPoints < start+10 )
|
||||
{
|
||||
WayPoints[NumPoints] = DestLoc;
|
||||
NumPoints++;
|
||||
}
|
||||
|
||||
Velocity = 500 * Normal(WayPoints[0] - Location) + C.Pawn.Velocity;
|
||||
}
|
||||
|
||||
|
||||
131
kf_sources/KFStoryGame/Classes/PawnWeldFire.uc
Normal file
131
kf_sources/KFStoryGame/Classes/PawnWeldFire.uc
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
class PawnWeldFire extends WeldFire;
|
||||
|
||||
var array <class<Actor> > ValidWeldTypes;
|
||||
|
||||
simulated Function Timer()
|
||||
{
|
||||
local Actor HitActor;
|
||||
local vector StartTrace, EndTrace, HitLocation, HitNormal,AdjustedLocation;
|
||||
local rotator PointRot;
|
||||
local int MyDamage;
|
||||
|
||||
If( !KFWeapon(Weapon).bNoHit )
|
||||
{
|
||||
MyDamage = MeleeDamage + Rand(MaxAdditionalDamage);
|
||||
|
||||
if ( KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo) != none && KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill != none )
|
||||
{
|
||||
MyDamage = float(MyDamage) * KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.Static.GetWeldSpeedModifier(KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo));
|
||||
}
|
||||
|
||||
PointRot = Instigator.GetViewRotation();
|
||||
StartTrace = Instigator.Location + Instigator.EyePosition();
|
||||
|
||||
if( AIController(Instigator.Controller)!=None && Instigator.Controller.Target!=None )
|
||||
{
|
||||
EndTrace = StartTrace + vector(PointRot)*weaponRange;
|
||||
Weapon.bBlockHitPointTraces = false;
|
||||
HitActor = Trace( HitLocation, HitNormal, EndTrace, StartTrace, true);
|
||||
Weapon.bBlockHitPointTraces = Weapon.default.bBlockHitPointTraces;
|
||||
|
||||
if( HitActor==None )
|
||||
{
|
||||
EndTrace = Instigator.Controller.Target.Location;
|
||||
Weapon.bBlockHitPointTraces = false;
|
||||
HitActor = Trace( HitLocation, HitNormal, EndTrace, StartTrace, true);
|
||||
Weapon.bBlockHitPointTraces = Weapon.default.bBlockHitPointTraces;
|
||||
}
|
||||
if( HitActor==None )
|
||||
HitLocation = Instigator.Controller.Target.Location;
|
||||
HitActor = Instigator.Controller.Target;
|
||||
}
|
||||
else
|
||||
{
|
||||
EndTrace = StartTrace + vector(PointRot)*weaponRange;
|
||||
Weapon.bBlockHitPointTraces = false;
|
||||
HitActor = Trace( HitLocation, HitNormal, EndTrace, StartTrace, true);
|
||||
Weapon.bBlockHitPointTraces = Weapon.default.bBlockHitPointTraces;
|
||||
}
|
||||
|
||||
LastHitActor = HitActor;
|
||||
|
||||
if( HitActor != none && IsValidWeldTarget(HitActor) && Level.NetMode!=NM_Client )
|
||||
{
|
||||
AdjustedLocation = Hitlocation;
|
||||
AdjustedLocation.Z = (Hitlocation.Z - 0.15 * Instigator.collisionheight);
|
||||
|
||||
HitActor.TakeDamage(MyDamage, Instigator, HitLocation , vector(PointRot),hitDamageClass);
|
||||
Spawn(class'KFWelderHitEffect',,, AdjustedLocation, rotator(HitLocation - StartTrace));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bool IsValidWeldTarget(actor HitActor)
|
||||
{
|
||||
local int idx;
|
||||
|
||||
/* No Welding of in-active breaker boxes */
|
||||
if(HitActor.IsA('KF_BreakerBoxNPC') && !KF_BreakerBoxNPC(HitActor).bActive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(idx = 0 ; idx < ValidWeldTypes.length ; idx ++)
|
||||
{
|
||||
if(ClassIsChildOf(HitActor.Class,ValidWeldTypes[idx]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function Actor GetWeldTarget()
|
||||
{
|
||||
local Actor A;
|
||||
local vector Dummy,End,Start;
|
||||
|
||||
if( AIController(Instigator.Controller)!=None )
|
||||
Return Pawn(Instigator.Controller.Target);
|
||||
Start = Instigator.Location+Instigator.EyePosition();
|
||||
End = Start+vector(Instigator.GetViewRotation())*weaponRange;
|
||||
Instigator.bBlockHitPointTraces = false;
|
||||
A = Instigator.Trace(Dummy,Dummy,End,Start,True);
|
||||
Instigator.bBlockHitPointTraces = Instigator.default.bBlockHitPointTraces;
|
||||
return A;
|
||||
}
|
||||
|
||||
function bool AllowFire()
|
||||
{
|
||||
local Actor WeldTarget;
|
||||
|
||||
WeldTarget = GetWeldTarget();
|
||||
|
||||
// Can't use welder, if no door.
|
||||
if ( WeldTarget == none || !IsValidWeldTarget(WeldTarget) )
|
||||
{
|
||||
if ( KFPlayerController(Instigator.Controller) != none )
|
||||
{
|
||||
KFPlayerController(Instigator.Controller).CheckForHint(54);
|
||||
|
||||
if ( FailTime + 0.5 < Level.TimeSeconds )
|
||||
{
|
||||
PlayerController(Instigator.Controller).ClientMessage(NoWeldTargetMessage, 'CriticalEvent');
|
||||
FailTime = Level.TimeSeconds;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return Weapon.AmmoAmount(ThisModeNum) >= AmmoPerFire ;
|
||||
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ValidWeldTypes(0) = class 'KFDoorMover'
|
||||
ValidWeldTypes(1) = class 'KF_StoryNPC_Static'
|
||||
}
|
||||
34
kf_sources/KFStoryGame/Classes/Pickup_MaintenanceKeyCard.uc
Normal file
34
kf_sources/KFStoryGame/Classes/Pickup_MaintenanceKeyCard.uc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Pickup_MaintenanceKeyCard
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Pickup_MaintenanceKeyCard extends KF_StoryInventoryPickup
|
||||
placeable;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DrawScale=1.0
|
||||
|
||||
bRenderIconThroughWalls = false
|
||||
bRender1PMesh = false
|
||||
|
||||
CollisionRadius = 25
|
||||
CollisionHeight = 25
|
||||
|
||||
bOrientOnSlope=true
|
||||
MaxHeldCopies = 1
|
||||
|
||||
UV2Texture = FadeColor'PatchTex.Common.PickupOverlay'
|
||||
CarriedMaterial = Texture 'KF_Swansong_Tex.Icons.Keycard_Icon_64'
|
||||
GroundMaterial = Colormodifier 'FrightYard_T.RemotePickupGroundIco_cm'
|
||||
|
||||
InventoryType = class 'Inv_MaintenanceKeyCard'
|
||||
MessageClass = class 'Msg_MaintenanceKeyCardNotification'
|
||||
|
||||
StaticMesh=StaticMesh'KF_Swansong_SM.Metro.SM_Keycard'
|
||||
|
||||
PrePivot=(X=0.f,Y=0.f,Z=25.f)
|
||||
|
||||
}
|
||||
31
kf_sources/KFStoryGame/Classes/Pickup_Nitroglycerin.uc
Normal file
31
kf_sources/KFStoryGame/Classes/Pickup_Nitroglycerin.uc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Pickup_Nitroglycerin
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Pickup_Nitroglycerin extends KF_StoryInventoryPickup;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Drawscale=0.25
|
||||
|
||||
StaticMesh = StaticMesh'KF_Swansong_SM.LAB.SM_Nitroglycerin_Bottle'
|
||||
|
||||
bRenderIconThroughWalls = false
|
||||
bRender1PMesh = false
|
||||
|
||||
CollisionRadius = 25
|
||||
CollisionHeight = 25
|
||||
|
||||
bOrientOnSlope=false
|
||||
MaxHeldCopies = 1
|
||||
|
||||
CarriedMaterial = Texture 'KF_Swansong_Tex.Icons.Nitroglycerin_Icon_64'
|
||||
GroundMaterial = Colormodifier 'FrightYard_T.RemotePickupGroundIco_cm'
|
||||
|
||||
InventoryType = class 'Inv_Nitroglycerin'
|
||||
MessageClass = class 'Msg_NitroglycerinNotification'
|
||||
|
||||
PrePivot=(X=0.f,Y=0.f,Z=100)
|
||||
}
|
||||
35
kf_sources/KFStoryGame/Classes/Pickup_PatriarchEyeBall.uc
Normal file
35
kf_sources/KFStoryGame/Classes/Pickup_PatriarchEyeBall.uc
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Pickup_PatriarchEyeBall
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Pickup_PatriarchEyeBall extends KF_StoryInventoryPickup;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DrawScale=2.f
|
||||
|
||||
bRenderIconThroughWalls = false
|
||||
bRender1PMesh = false
|
||||
|
||||
CollisionRadius = 25
|
||||
CollisionHeight = 25
|
||||
|
||||
bOrientOnSlope=true
|
||||
MaxHeldCopies = 1
|
||||
|
||||
UV2Texture = FadeColor'PatchTex.Common.PickupOverlay'
|
||||
CarriedMaterial = Texture 'KF_Swansong_Tex.Icons.Eyeball_Icon_64'
|
||||
GroundMaterial = Colormodifier 'FrightYard_T.RemotePickupGroundIco_cm'
|
||||
|
||||
InventoryType = class 'Inv_PatriarchEyeBall'
|
||||
MessageClass = class 'Msg_EyeBallNotification'
|
||||
|
||||
StaticMesh=StaticMesh 'kf_gore_trip_sm.gibbs.eyeball'
|
||||
Skins(0)=Texture 'kf_fx_trip_t.Gore.eyeball_diff'
|
||||
|
||||
PrePivot=(X=0,Y=0,Z=11.5)
|
||||
|
||||
DroppedSound=Sound'KFPawnDamageSound.MeleeDamageSounds.bathitflesh2'
|
||||
}
|
||||
31
kf_sources/KFStoryGame/Classes/Pickup_Thermite.uc
Normal file
31
kf_sources/KFStoryGame/Classes/Pickup_Thermite.uc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
Pickup_Thermite
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class Pickup_Thermite extends KF_StoryInventoryPickup;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DrawScale = 0.6
|
||||
|
||||
StaticMesh = StaticMesh'KF_Swansong_SM.Metro.SM_Thermite'
|
||||
|
||||
bRenderIconThroughWalls = false
|
||||
bRender1PMesh = false
|
||||
|
||||
CollisionRadius = 40
|
||||
CollisionHeight = 10
|
||||
|
||||
bOrientOnSlope=false
|
||||
MaxHeldCopies = 1
|
||||
PrePivot=(X=0,Y=0,Z=18)
|
||||
|
||||
UV2Texture = FadeColor'PatchTex.Common.PickupOverlay'
|
||||
CarriedMaterial = Texture 'KF_Swansong_Tex.Icons.Thermite_Icon_64'
|
||||
GroundMaterial = Colormodifier 'FrightYard_T.RemotePickupGroundIco_cm'
|
||||
|
||||
InventoryType = class 'Inv_Thermite'
|
||||
MessageClass = class 'Msg_ThermiteNotification'
|
||||
}
|
||||
48
kf_sources/KFStoryGame/Classes/RespawnTimer.uc
Normal file
48
kf_sources/KFStoryGame/Classes/RespawnTimer.uc
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
RespawnTimer
|
||||
--------------------------------------------------------------
|
||||
|
||||
Modified volumeTimer for use with KF_StoryCheckPointVolume actors.
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class RespawnTimer extends info;
|
||||
|
||||
var KF_StoryCheckPointVolume CheckPoint;
|
||||
var float TimerFrequency;
|
||||
var bool bInitialised;
|
||||
|
||||
|
||||
function PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
CheckPoint = KF_StoryCheckPointVolume(Owner);
|
||||
SetTimer(1.0, false);
|
||||
}
|
||||
|
||||
function Timer()
|
||||
{
|
||||
if(!bInitialised)
|
||||
{
|
||||
bInitialised = true;
|
||||
SetTimer(TimerFrequency, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckPoint.RespawnTimerPop();
|
||||
}
|
||||
}
|
||||
|
||||
function Reset()
|
||||
{
|
||||
bInitialised = false;
|
||||
Timer();
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
TimerFrequency=2.000000
|
||||
}
|
||||
61
kf_sources/KFStoryGame/Classes/StaticMeshActor_Hideable.uc
Normal file
61
kf_sources/KFStoryGame/Classes/StaticMeshActor_Hideable.uc
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
StaticMeshActor_Hideable
|
||||
--------------------------------------------------------------
|
||||
|
||||
StaticMeshActor which can be toggled on / off
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class StaticMeshActor_Hideable extends StaticMeshActor;
|
||||
|
||||
var bool bInitialHidden;
|
||||
|
||||
var () bool bNoCollisionWhileHidden;
|
||||
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
bInitialhidden = bHidden;
|
||||
}
|
||||
|
||||
|
||||
simulated function Trigger( actor Other, pawn EventInstigator )
|
||||
{
|
||||
bHidden = !bHidden;
|
||||
if(bNoCollisionWhileHidden)
|
||||
{
|
||||
if(bHidden)
|
||||
{
|
||||
SetCollision(false,false);
|
||||
bBlockZeroExtentTraces = false;
|
||||
bBlockNonZeroExtentTraces = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCollision(default.bCollideActors,default.bBlockActors);
|
||||
bBlockZeroExtentTraces = default.bBlockZeroExtentTraces;
|
||||
bBlockNonZeroExtentTraces = default.bBlockNonZeroExtentTraces;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Reset()
|
||||
{
|
||||
bHidden = bInitialhidden;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bNoCollisionWhileHidden = true
|
||||
bStatic = false
|
||||
bAlwaysRelevant = true
|
||||
bNoDelete = true
|
||||
RemoteRole=ROLE_SimulatedProxy
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
58
kf_sources/KFStoryGame/Classes/StoryInventoryAttachment.uc
Normal file
58
kf_sources/KFStoryGame/Classes/StoryInventoryAttachment.uc
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
--------------------------------------------------------------
|
||||
StoryInventoryAttachment
|
||||
--------------------------------------------------------------
|
||||
|
||||
Third person actor which represents a KF_StoryInventoryItem while
|
||||
carried by a player.
|
||||
|
||||
Author : Alex Quick
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
class StoryInventoryAttachment extends InventoryAttachment;
|
||||
|
||||
var KF_StoryInventoryItem StoryOwner;
|
||||
|
||||
|
||||
function InitFor(Inventory I)
|
||||
{
|
||||
Instigator = I.Instigator;
|
||||
|
||||
StoryOwner = KF_StoryInventoryItem(I);
|
||||
if(StoryOwner != none)
|
||||
{
|
||||
SetStaticMesh(StoryOwner.PickupSM);
|
||||
LinkMesh(StoryOwner.Mesh);
|
||||
AmbientGlow = StoryOwner.AmbientGlow;
|
||||
SetDrawScale3D(StoryOwner.DrawScale3D);
|
||||
SetDrawScale(StoryOwner.DrawScale);
|
||||
SetDrawType(StoryOwner.DrawType);
|
||||
|
||||
// Lighting
|
||||
|
||||
if(StoryOwner.StoryPickupBase != none)
|
||||
{
|
||||
LightType = StoryOwner.StoryPickupBase.LightType;
|
||||
LightBrightness = StoryOwner.StoryPickupBase.LightBrightness;
|
||||
LightRadius = StoryOwner.StoryPickupBase.LightRadius;
|
||||
LightHue = StoryOwner.StoryPickupBase.lighthue;
|
||||
bUseDynamicLights = StoryOwner.StoryPickupBase.bUseDynamicLights;
|
||||
LightSaturation = StoryOwner.StoryPickupBase.LightSaturation;
|
||||
bDynamicLight = StoryOwner.StoryPickupBase.bDynamicLight;
|
||||
|
||||
bLightChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bActorShadows=true
|
||||
DrawType = DT_StaticMesh;
|
||||
bCollideActors=False
|
||||
bCollideWorld=False
|
||||
bBlockActors=False
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue