//----------------------------------------------------------- // //----------------------------------------------------------- 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 TelList; var bool bTelsInit,bHasTeles,bInitTriggerActs,bCurrentlyOpen,bAlwaysClosed; var array 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 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