rott/kf_sources/KFMod/Classes/ShopVolume.uc
2026-07-14 20:27:09 +07:00

217 lines
6.0 KiB
Ucode

//-----------------------------------------------------------
//
//-----------------------------------------------------------
class ShopVolume extends Volume;
var() string URL;
var() float EnabledProbability; // How big chance is it that I get selected to be open on wave start?
var() bool bAlwaysEnabled; // Should the trader always be open (even when its not my turn)?
var array<Teleporter> TelList;
var bool bTelsInit,bHasTeles,bInitTriggerActs,bCurrentlyOpen,bAlwaysClosed;
var array<Actor> TriggeringActors;
var NavigationPoint BotPoint;
var WeaponLocker MyTrader;
// this shop is only used in the Objective mode gametype.
var(Advanced) const bool bObjectiveModeOnly;
function Touch( Actor Other )
{
if( Pawn(Other)!=None && PlayerController(Pawn(Other).Controller)!=None && KFGameType(Level.Game)!=None && !KFGameType(Level.Game).bWaveInProgress )
{
if( !bCurrentlyOpen )
{
BootPlayers();
return;
}
MyTrader.SetOpen(true);
if( KFPlayerController(Pawn(Other).Controller) !=None )
{
KFPlayerController(Pawn(Other).Controller).SetShowPathToTrader(false);
KFPlayerController(Pawn(Other).Controller).CheckForHint(52);
}
PlayerController(Pawn(Other).Controller).ReceiveLocalizedMessage(Class'KFMainMessages',3);
if ( KFPlayerController(Pawn(Other).Controller) != none && !KFPlayerController(Pawn(Other).Controller).bHasHeardTraderWelcomeMessage )
{
// Have Trader say Welcome to players
if ( KFGameType(Level.Game).WaveCountDown >= 30 )
{
KFPlayerController(Pawn(Other).Controller).ClientLocationalVoiceMessage(Pawn(Other).PlayerReplicationInfo, none, 'TRADER', 7);
KFPlayerController(Pawn(Other).Controller).bHasHeardTraderWelcomeMessage = true;
}
}
}
else if( Other.IsA('KF_StoryInventoryPickup') )
{
if( !bCurrentlyOpen )
{
BootPlayers();
return;
}
}
}
function UnTouch( Actor Other )
{
if( Pawn(Other)!=None && PlayerController(Pawn(Other).Controller)!=None && KFGameType(Level.Game)!=None )
MyTrader.SetOpen(false);
}
function UsedBy( Pawn user )
{
// Set the pawn to an idle anim so he wont keep making footsteps
User.SetAnimAction(User.IdleWeaponAnim);
if( KFPlayerController(user.Controller)!=None && KFGameType(Level.Game)!=None && !KFGameType(Level.Game).bWaveInProgress )
KFPlayerController(user.Controller).ShowBuyMenu(string(MyTrader.Tag),KFHumanPawn(user).MaxCarryWeight);
}
function InitTeleports()
{
local NavigationPoint N,BestN;
local int i;
local float Dist,BDist;
bTelsInit = True;
For( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
{
if( Teleporter(N)!=None && string(N.Tag)~=URL )
{
TelList.Length = i+1;
TelList[i] = Teleporter(N);
i++;
bHasTeles = True;
}
Dist = VSize(N.Location-Location);
if( Dist<2000 && (BestN==None || BDist>Dist) && FastTrace(N.Location,Location) )
{
BestN = N;
BDist = Dist;
}
}
BotPoint = BestN;
}
function bool BootPlayers()
{
local KFHumanPawn Bootee;
local int i,idx;
local bool bResult;
local int NumTouching,NumBooted;
local array<Teleporter> UnusedSpots;
local bool bBooted;
if( !bTelsInit )
InitTeleports();
if( !bHasTeles )
Return False; // Wtf?
UnusedSpots = TelList;
// log("******************************************************");
/* TouchingActors iterator doesn't work here because the players leave the array when being teleported which
means that the array length changes *while* being iterated and produces incorrect results. As a solution we're gonna
use the Touching array and back the index up after each successful port. */
for ( idx = Touching.length-1 ; idx >= 0 ; idx -- )
{
Bootee = KFHumanPawn(Touching[idx]);
if(Bootee == none)
{
if(Touching[idx].IsA('KF_StoryInventoryPickup'))
{
Touching[idx].SetLocation(TelList[Rand(TelList.length)].Location + (vect(0,0,1) * Touching[idx].CollisionHeight)) ;
Touching[idx].SetPhysics(PHYS_Falling);
Touching[idx].SetOwner(Touching[idx].Owner); // to force NetDirty
}
continue ;
}
// log(self@"CONTROLLERLIST :: "@Bootee);
NumTouching ++ ;
if( PlayerController(Bootee.Controller)!=none )
{
PlayerController(Bootee.Controller).ReceiveLocalizedMessage(Class'KFMainMessages');
PlayerController(Bootee.Controller).ClientCloseMenu(true, true);
}
// Teleport to a random teleporter in this local area, if more than one pick random.
i = Rand(UnusedSpots.Length);
if ( Bootee.IsA('Pawn') )
Bootee.PlayTeleportEffect(false, true);
bBooted = UnusedSpots[i].Accept( Bootee, self ) ;
if(bBooted)
{
NumBooted ++;
UnusedSpots.Remove(i,1); // someone is being teleported here. We can't have the next guy spawning on top of him.
}
// log(" Successful Boot ? : "@bBooted);
}
bResult = NumBooted >= NumTouching;
Return bResult;
}
function OpenShop()
{
local Actor A;
local int i,l;
if( bCurrentlyOpen )
return;
bCurrentlyOpen = True;
if( !bInitTriggerActs )
{
bInitTriggerActs = True;
if( Event!='' )
{
foreach DynamicActors(Class'Actor',A,Event)
TriggeringActors[TriggeringActors.Length] = A;
}
}
l = TriggeringActors.Length;
for( i=0; i<l; i++ )
TriggeringActors[i].Trigger(Self,None);
}
function CloseShop()
{
local int i,l;
if( !bCurrentlyOpen )
return;
bCurrentlyOpen = False;
l = TriggeringActors.Length;
for( i=0; i<l; i++ )
TriggeringActors[i].Trigger(Self,None);
}
function InitTriggerActors()
{
local Actor A;
if( !bInitTriggerActs )
{
bInitTriggerActs = True;
if( Event!='' )
{
foreach DynamicActors(Class'Actor',A,Event)
TriggeringActors[TriggeringActors.Length] = A;
}
}
}
defaultproperties
{
EnabledProbability=1
}