Prepare fixtures

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

View file

@ -0,0 +1,50 @@
class ACTION_DamagePawnX extends ACTION_DamagePawn;
var(Action) int MaxVictims;
function bool InitActionFor(ScriptedController C)
{
local Actor A;
local Pawn Victim, Instigator;
local int Damage, count;
switch ( DamageInstigator ) {
case DMG_Instigator: Instigator = C.Instigator; break;
case DMG_Myself: Instigator = C.Pawn; break;
}
ForEach C.DynamicActors(VictimClass, A, VictimTag) {
Victim = Pawn(A);
if ( Victim.Health <= 0 || Victim.bDeleteMe )
continue;
if ( DamageInstigator == DMG_Himself )
Instigator = Victim;
switch ( DamageCalculation )
{
case DCALC_Amount: Damage = RandRange(MinDamageAmount, MaxDamageAmount); break;
case DCALC_HealthPct: Damage = Victim.Health * ( MinDamagePct + frand()*(MaxDamagePct - MinDamagePct) ); break;
case DCALC_HealthMaxPct: Damage = Victim.HealthMax * ( MinDamagePct + frand()*(MaxDamagePct - MinDamagePct) ); break;
}
Victim.TakeDamage(Damage, Instigator, Victim.Location, vect(0,0,0), DamageType);
if ( ++count >= MaxVictims )
break;
}
return false;
}
function string GetActionString()
{
return ActionString @ GetItemName(String(VictimClass)) @ VictimTag;
}
defaultproperties
{
MaxVictims=1
DamageType=Class'Engine.Suicided'
}

View file

@ -0,0 +1,27 @@
class ACTION_WeldDoor extends ScriptedAction;
var(Action) name DoorTag;
var(Action) float WeldAmount;
function bool InitActionFor(ScriptedController C)
{
local KFDoorMover door;
ForEach C.DynamicActors(class'KFDoorMover', door, DoorTag) {
if ( !door.bClosed )
break;
if ( WeldAmount < 0 )
door.MyTrigger.UnWeld(min(door.MyTrigger.WeldStrength, -WeldAmount), false, C.Pawn);
else
door.MyTrigger.AddWeld(WeldAmount, false, C.Pawn);
break;
}
return false;
}
defaultproperties
{
}

View file

@ -0,0 +1,336 @@
class KF_StoryCheckPointVolumeSE extends KF_StoryCheckPointVolume;
var array<PlayerStart> ForeignPSList;
var transient bool bPSListInit;
simulated function PostBeginPlay()
{
local KF_DialogueSpot DlgSpot;
if( Level.NetMode==NM_Client )
return;
/* No KFO Gametype, no Initialization */
StoryGI = KFStoryGameInfo(Level.Game);
if(StoryGI == none)
{
return;
}
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 ;
}
}
// copy-pasted from KFStoryGameInfo to allow use in non-story games
function int GetTotalActivePlayers()
{
local int LivingCount;
local Controller C;
for ( C=Level.ControllerList; C!=None; C=C.NextController )
{
if ((C.PlayerReplicationInfo != None) &&
C.bIsPlayer && !C.PlayerReplicationInfo.bOutOfLives &&
!C.PlayerReplicationInfo.bOnlySpectator )
{
LivingCount ++ ;
}
}
// log("TOTAL PLAYERS : "@LivingCount);
return LivingCount ;
}
// bIncludeBots now can be enabled without bRespawnPlayers
function CheckPointActivated( Pawn CheckPointInstigator, bool bForceActivate, optional bool bShowMessage)
{
local KF_StoryCheckPointVolume OldCheckpoint;
local Controller C;
/* Check for a human controlled pawn */
if( CheckPointInstigator != none && CheckPointInstigator.Controller != none ) {
ActivatingPlayer = CheckPointInstigator.Controller;
if(ActivatingPlayer != none && PlayerController(ActivatingPlayer) != none &&
ActivatingPlayer.Pawn != none )
Instigator = ActivatingPlayer.Pawn ;
}
if( !bForceActivate && bRequiresWholeTeam && GetNumPlayersInVolume() < 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 || bIncludeBots )
{
if ( RespawnDelay > 0 )
DelayedRespawnDeadPlayers();
else
RespawnTimerPop();
}
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);
}
}
}
function InitPlayerStarts()
{
local NavigationPoint N;
local PlayerStart PS;
for( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint ) {
PS = PlayerStart(N);
if( PS!=None ) {
if(Encompasses(PS) )
PSList[PSList.Length] = PS;
else
ForeignPSList[ForeignPSList.Length] = PS;
}
}
bPSListInit = true;
}
function DebugPlayerStarts()
{
local NavigationPoint N;
local PlayerStart PS;
ClearStayingDebugLines();
for( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint ) {
PS = PlayerStart(N);
if( PS!=None ) {
if(PS.bEnabled)
{
DrawStayingDebugLine(N.Location, N.Location + (100 * vect(0,0,1)), 0,255,0);
}
else
{
DrawStayingDebugLine(N.Location, N.Location + (100 * vect(0,0,1)), 255,0,0);
}
}
}
}
function UpdateSpawnAvailability()
{
local int i;
if ( !bPSListInit )
InitPlayerStarts();
if( PSList.Length>0 ) {
for ( i=0; i<PSList.Length; ++i )
PSList[i].bEnabled = true;
for ( i=0; i<ForeignPSList.Length; ++i )
ForeignPSList[i].bEnabled = false;
// debug
//DebugPlayerStarts();
}
else {
for ( i=0; i<ForeignPSList.Length; ++i )
ForeignPSList[i].bEnabled = true;
log("Warning - No Playerstarts associated with "@self@": Respawns may fail.");
}
}
// allows respawning bots only (excluding players)
function RespawnDeadPlayers()
{
local int i;
local Controller C;
local KFPlayerController KFPC;
local PlayerController PC;
local KFPlayerReplicationInfo KFPRI;
local bool bWaveInProgress, bBalanceTeams;
bPendingRespawn = false;
bWaveInProgress = KFGameType(Level.Game).bWaveInProgress;
bBalanceTeams = KFGameType(Level.Game).bBalanceTeams;
KFGameType(Level.Game).bWaveInProgress = false;
KFGameType(Level.Game).bBalanceTeams = 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 )
continue;
if ( C.PlayerReplicationInfo.bBot ) {
if ( !bIncludeBots )
continue;
}
else if ( !bRespawnPlayers )
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;
}
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 ( C.Pawn != none ) {
if ( bTeleportStragglers ) {
for ( i=0; i<PSList.Length; ++i )
if ( PSList[i].Accept(C.Pawn, none) )
break;
}
if( PC != none )
PC.ClientSetViewTarget(PC.Pawn);
}
}
}
KFGameType(Level.Game).bWaveInProgress = bWaveInProgress;
KFGameType(Level.Game).bBalanceTeams = bBalanceTeams;
LastRespawnedPlayer = none;
/* Full Checkpoint restart (everyone was wiped out) */
if(bPendingFullRestart && StoryGI != none)
{
bPendingFullRestart = false;
StoryGI.NotifyTeamRestarted();
}
}
function TeleportLivingPlayers()
{
local Controller C;
local bool bTeleportMe;
local int i;
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
&& ((C.PlayerReplicationInfo.bBot && bIncludeBots) || (!C.PlayerReplicationInfo.bBot && bRespawnPlayers)) )
{
if(TeleportExclusionVolume != none)
bTeleportMe = !TeleportExclusionVolume.Encompasses(C.Pawn);
else
bTeleportMe = TeleportStragglerDist == 0 || VSize(C.Pawn.Location - Location) >= TeleportStragglerDist;
if(bTeleportMe){
for ( i=0; i<PSList.Length; ++i )
if ( PSList[i].Accept(C.Pawn, none) )
break;
if ( i == PSList.Length )
log("Unable to teleport " $ C.Pawn $ " to " $ self, 'StoryCheckPoint');
}
}
}
}
}
function SaveStoryState()
{
if ( StoryGI != none )
super.SaveStoryState();
}
defaultproperties
{
}

View file

@ -0,0 +1,28 @@
class ScrnBotPawn extends KFHumanPawn;
simulated function PostNetBeginPlay()
{
local SquadAI S;
super.PostNetBeginPlay();
// C&P from UnrealPawn, because it seems like Squad isn't set for pawns placed on level
if ( Role == ROLE_Authority && Bot(Controller) != none && Bot(Controller).Squad == none ) {
ForEach DynamicActors(class'SquadAI',S,SquadName)
break;
if ( S == None )
S = spawn(class'SquadAI');
S.Tag = SquadName;
if ( bIsSquadLeader || (S.SquadLeader == None) ) {
S.SetLeader(Controller);
S.Team = UnrealTeamInfo(Controller.PlayerReplicationInfo.Team);
}
S.AddBot(Bot(Controller));
}
}
defaultproperties
{
SquadName="BotSquad"
ControllerClass=Class'ScrnTestGroundsUtil.ScrnInvasionBot'
}

View file

@ -0,0 +1,51 @@
class ScrnInvasionBot extends KFInvasionBot;
// function InitPlayerReplicationInfo()
// {
// super.InitPlayerReplicationInfo();
// if ( !PlayerReplicationInfo.bNoTeam )
// Level.Game.ChangeTeam(self, 1, true);
// }
function array<class<Pickup> > GetLegalPurchases()
{
local int i,j;
local KFLevelRules KFLR;
local array<class<Pickup> > RetList;
KFLR = KFGameType(Level.game).KFLRules;
for(i=0; i<KFLR.MediItemForSale.length; i++ )
if( CanAfford(KFLR.MediItemForSale[i] ) )
RetList[j++] = KFLR.MediItemForSale[i];
for(i=0; i<KFLR.SuppItemForSale.length; i++ )
if( CanAfford(KFLR.SuppItemForSale[i] ) )
RetList[j++] = KFLR.SuppItemForSale[i];
for(i=0; i<KFLR.ShrpItemForSale.length; i++ )
if( CanAfford(KFLR.ShrpItemForSale[i] ) )
RetList[j++] = KFLR.ShrpItemForSale[i];
for(i=0; i<KFLR.CommItemForSale.length; i++ )
if( CanAfford(KFLR.CommItemForSale[i] ) )
RetList[j++] = KFLR.CommItemForSale[i];
for(i=0; i<KFLR.BersItemForSale.length; i++ )
if( CanAfford(KFLR.BersItemForSale[i] ) )
RetList[j++] = KFLR.BersItemForSale[i];
for(i=0; i<KFLR.FireItemForSale.length; i++ )
if( CanAfford(KFLR.FireItemForSale[i] ) )
RetList[j++] = KFLR.FireItemForSale[i];
for(i=0; i<KFLR.DemoItemForSale.length; i++ )
if( CanAfford(KFLR.DemoItemForSale[i] ) )
RetList[j++] = KFLR.DemoItemForSale[i];
for(i=0; i<KFLR.NeutItemForSale.length; i++ )
if( CanAfford(KFLR.NeutItemForSale[i] ) )
RetList[j++] = KFLR.NeutItemForSale[i];
return RetList;
}
defaultproperties
{
PawnClass=Class'ScrnTestGroundsUtil.ScrnBotPawn'
}

View file

@ -0,0 +1,17 @@
//=============================================================================
// TriggerSE: checks DamageType for ClassProximityType
//=============================================================================
class TriggerSE extends Trigger;
function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation,
Vector momentum, class<DamageType> damageType, optional int HitIndex)
{
if ( ClassProximityType != none && !ClassIsChildOf(damageType, ClassProximityType) )
return;
super.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType, HitIndex);
}
defaultproperties
{
}

View file

@ -0,0 +1,38 @@
//=============================================================================
// UseTriggerSE: prevents message spamming and using by monsters
//=============================================================================
class UseTriggerSE extends UseTrigger;
var(UseTrigger) float MessageCooldown;
var(UseTrigger) bool bAllowUsingByAI;
var transient float NextMessageTime;
function bool SelfTriggered()
{
return true;
}
function UsedBy( Pawn user )
{
TriggerEvent(Event, self, user);
}
function Touch( Actor Other )
{
if ( Pawn(Other) != None ) {
// Send a string message to the toucher.
if( Message != "" && Level.TimeSeconds > NextMessageTime ) {
Pawn(Other).ClientMessage( Message );
NextMessageTime = Level.TimeSeconds + MessageCooldown;
}
if ( bAllowUsingByAI && AIController(Pawn(Other).Controller) != None )
UsedBy(Pawn(Other));
}
}
defaultproperties
{
MessageCooldown=5.000000
Texture=Texture'Engine.SubActionTrigger'
}

View file

@ -0,0 +1,13 @@
<html>
<head><title>Index of /kf_sources/ScrnTestGroundsUtil/Classes/</title></head>
<body>
<h1>Index of /kf_sources/ScrnTestGroundsUtil/Classes/</h1><hr><pre><a href="../">../</a>
<a href="ACTION_DamagePawnX.uc">ACTION_DamagePawnX.uc</a> 01-Jul-2020 18:12 1356
<a href="ACTION_WeldDoor.uc">ACTION_WeldDoor.uc</a> 01-Jul-2020 18:12 624
<a href="KF_StoryCheckPointVolumeSE.uc">KF_StoryCheckPointVolumeSE.uc</a> 01-Jul-2020 18:12 9648
<a href="ScrnBotPawn.uc">ScrnBotPawn.uc</a> 01-Jul-2020 18:12 867
<a href="ScrnInvasionBot.uc">ScrnInvasionBot.uc</a> 01-Jul-2020 18:12 1724
<a href="TriggerSE.uc">TriggerSE.uc</a> 01-Jul-2020 18:12 645
<a href="UseTriggerSE.uc">UseTriggerSE.uc</a> 01-Jul-2020 18:12 1033
</pre><hr></body>
</html>

View file

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