Could be asleep, typing random messages instead.

[RELEASED] [UT] The Last Fortress - Final

For discussion and promotion of Unreal Engine single-player campaigns, mapping projects and total conversions.

Moderators: Semfry, ividyon

Doublez-Down
Skaarj Warlord Skaarj Warlord
Posts: 993
Joined: 27 Feb 2010, 22:46

Subject: Re: [Released] The Last Fortress - Final

Post Posted: 17 Dec 2010, 02:06

Salsa - I didn't mean "real" elevators, as yeah that would be really out of place. I meant invisible ones that moved you up slowly like you were climbing up the rope. Waff already answered the reasons against doing that though, and they all make sense. I think I opened up the map in the editor once just to see what the node count was and started laughing my ass off at how many headaches it must have given you. That said, some small metal ladders somewhere (like you see on real docks) might make sense, but yeah more bsp.

The ropes aren't that big of a distractor though tbh, once you get the hang of them.
I swear to god this forum isn't going to evaporate into ether within the next hour or so. - Bug Horse

User avatar TheIronKnuckle
Gilded Claw Gilded Claw
Posts: 1967
Joined: 12 Nov 2007, 07:21
Location: Riding my bicycle from the highest hill in Sydney to these forums

Subject: Re: [Released] The Last Fortress - Final

Post Posted: 22 Dec 2010, 11:29

Waffnuffly wrote:I guess you could explain away the ropes as things the Skaarj wrapped around poles for their own convenience in the event that any of them accidentally fell in the water during construction (due to the structural damage caused by their airborne artillery strikes). The original occupants of the fortress (i.e. the humans and Nali survivors) most definitely wouldn't have made it so easy.


I assumed they were part of the materials that that scientist dude bullshitted the skaarj into letting him install all over the place, like the chains. :P

and god damn waff, you're a powerhouse. I obviously need to try some of that half hour work half hour play stuff you swear by :lol:
ImageIgnorance is knowing anything
And only idiots know everything

User avatar Buff Skeleton
>:E >:E
Posts: 4173
Joined: 15 Dec 2007, 00:46

Subject: Re: [Released] The Last Fortress - Final

Post Posted: 22 Dec 2010, 15:05

TheIronKnuckle wrote:I assumed they were part of the materials that that scientist dude bullshitted the skaarj into letting him install all over the place, like the chains. :P

and god damn waff, you're a powerhouse. I obviously need to try some of that half hour work half hour play stuff you swear by :lol:

The ropes aren't metal, though; they're mostly unrelated. And I actually haven't done much of that 30/30 stuff lately, which probably explains my lack of progress on some fronts :I
Image

User avatar Core
Skaarj Assassin Skaarj Assassin
Posts: 106
Joined: 15 Mar 2010, 17:16
Location: ../System/
Contact:

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 28 Dec 2010, 00:05

Waff, there was this coop problem of the smokegenerators in the skybox. Don't know if you have dealt with that already, but I have a replacement class ready that i'm planning to implement in the next update of ecoop to replace smokegenerators in general (eg. keeping the smoke spawns clientside instead). I could post the code here if you haven't worked on that yet, as mapping them inside a map could save on initial replication on some smokegen properties instead of having this as a replacement through mut.


As for that ladder thing, I liked some of the ideas made here, as they could come in handy for my next update of the portalmap, where i have some ladders as well. I currently use very small invisible ladderbrushes for them, But these are so small that you instantly ascend them & always fall when trying to descend.

I have some scripts ready now that will allow players to be stationary on a ladder, move up/down with either crouch/jump keys or the movement keys (at a speed depending on their viewrotation in the latter case), while still allowing him to move off whenever he wants (eg. moving relatively horizontal). it also implements a climbradius to which the player is restricted during his movement up/down and also a walk animation & editable ambientsound for during the movement.

This is achieved without any custom playerclass or gametype & compatible with coop. (I assume the gametype was meant to change the spawnclass, but this can also be done through an embedded mut's modifylogin to achieve game independance).

I've currently imlemented this as a zoneinfo inside an invisible zone portal volume brush, as well as trough an actor's/trigger's collisionradius (Qtit style), though I think with the latter method you're restricted to 4 simultaneous players on a ladder (touching arraycount).


My portalmap update is sheduled for the long run, but if you're intrested in implementing any of this in TLF, let me know and I'll do some more tests to make sure it's bugfree & post the code :wink: .

User avatar Buff Skeleton
>:E >:E
Posts: 4173
Joined: 15 Dec 2007, 00:46

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 28 Dec 2010, 01:19

Yeah I'd be interested in both of those things. I haven't found a good ladder solution yet; qtit tried some stuff out but it was still pretty buggy and not really usable. For the time being, I'm still using the original ladders and may just stick with them if nothing else comes up that's better, but improved smoke gens for the skybox would probably be a good idea.
Image

User avatar Core
Skaarj Assassin Skaarj Assassin
Posts: 106
Joined: 15 Mar 2010, 17:16
Location: ../System/
Contact:

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 28 Dec 2010, 21:07

Ok, I'll try to test those things extensively one of these days, and post the thing probably before the weekend. I'll keep you informed if I find any issues.

User avatar Core
Skaarj Assassin Skaarj Assassin
Posts: 106
Joined: 15 Mar 2010, 17:16
Location: ../System/
Contact:

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 02 Jan 2011, 20:20

Here's the ladder script I was talking about. Warped it in a spoiler as it's abit lengthy. Hope you like it, but don't feel obliged to use it if you don't.

I'm glad I did this earlier then I wanted, as it revealed a couple of bugs with some of the skeletal models (xanII/warboss/ChicoMarine) all missing the 'walk' animation (walking without a gun) and an accessed none in feigningdeath state (if not having a weapon). I can address these now in my custom playerclass. The code is spiced with comments so it should all be self-explenatory.

When using this for TLF you may have to increase the radius of some of the ladders to have the player move properly (eg. around a hanging rope) or have him circumvent obstacles in his climbing path (eg. first floor climb near the second or third titan).

[spoiler]

Code: Select all

//====================================================================================================================================
// ELadder
// Some kind of ladder script...
//====================================================================================================================================
// CopyRight 2010 - End Of Times
// Author: Core
// Release  Date: 01/01\11
// Version: V2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.11
//=====================================================================================================================================
// IMPORTANT: IT IS STRICTLY PROHIBITED AND ABSOLUTELY FORBIDDEN TO USE THE SLIGHTEST PEACE OF CODE FROM THIS CLASS WITHOUT MY EXPLICIT
// PERMISSION!!! CRIMINAL CODERS CAUGHT USING THIS CODE ILLEGITIMATELY WILL BE SENTENCED TO DEATH BY HANGING AFTER BEING BLOWTORCHED
// WITH A KEROSINE DRIVEN TORCH AND SHOWERED IN AN EMULSION OF HOT NITRIC ACID, PEE & SHIT. THIS WILL BE CONFORM THE SPECIFICATIONS
// OF A JURISDICTION OF CHOICE OF THE AUTHOR. HERE'S A PICTURE OF HOW YOU MIGHT END UP AFTER TREATMENT: c:\pic.jpg. YOU GOT THE IDEA?
// WHAT? YOU DONT WANT TO ILLEGALLY USE THIS CODE ANYMORE? GOOD! KEEP IT THAT WAY. you betta save then sry...
//=====================================================================================================================================
// Disclaimer: The author is not responsible for any effect of this code that can be defined as negative, or that will cost the author
// more or less then 0€. Granted permission & due credit is given, it is allowed to make money with this code, at the condition of
// Paying 99.99% of the total revenue of the software this code was used in to the author. Does this sound like a joke? It isn't.
//=====================================================================================================================================
// Usage: Anyone can use this and modify at will, granted due credit and different name is given :)
//=====================================================================================================================================
// Note: It's better not to have multiple ladders collide with each other, even though that shouldn't cause problems. Instead finetune
// the collisionradius & climbradius to fit the climbing needs. Notice that if the climbradius is not specified, it'll take the value
// of the collision radius instead and increase the latter.
//=====================================================================================================================================
class ELadder extends Triggers;


//Radius to wich player is restricted when moving up or down..
var () float ClimbRadius;

//Override ClimbRadius restriction at top & bottom of ladder, may increase the risk of falling unwillingly at both ends..
var () bool bMoveFreeAtEnds;

//Minimum absolute Z-velocity that flags the player as climbing
//i.e. no restrictions apply when |Z velocity| is smaller then or equal to this (player can then jump off for example)
var () float ClimbVelocityFlag;

//The Z-speed at wich the player climbs up or down with crouch/jump. This is also the Max. Speed.
var () float ClimbSpeed;

//Optional AmbientSound to play when moving on the ladder (climbing) - Eg. player hears whether it's climbing/not climbing to jump off..
//Note that this will override ambientsounds assigned to player by some inv. (eg. speed relic)
var () sound AmbientClimbSound;

//Support for triggertoggle..
var () bool bActive;


//Internal, saves on calcs
var float ClimbRadSquare;

//ClientSide Autonomous Local Player Ref.
var PlayerPawn LocalPP;

/*/We're not a replacement...
replication
{
   //Only replicate when necessary..(eg. replacement)
   reliable if (Role==ROLE_Authority && bNetInitial)
      ClimbRadius, bMoveFreeAtEnds, ClimbVelocityFlag, ClimbSpeed;
}*/



function PreBeginPlay()
{
   Super.PreBeginPlay();

   //Replacing qTitLadder..
   if (Owner != None)
      SetCollisionSize(Owner.CollisionRadius, Owner.CollisionHeight);
   //SetOwner(None);

   //use CollisionRad as climbRad if not specified by mapper
   if (ClimbRadius ~= 0.0)
   {
      ClimbRadius = CollisionRadius;
      ClimbRadSquare = ClimbRadius * ClimbRadius;
      //Diff. between rad & climbrad should be bigger then the max possible horizontal movement between two ticks..
      SetCollisionSize(1.25*ClimbRadius, CollisionHeight);
   }

   SetCollision(bActive,,);

}


//We're toggled on & off through triggering (eg. a ladder was blown apart)
function Trigger(Actor Other, Pawn EventInstigator)
{
   //Toggle
   bActive = !bActive;
   //Rep'd
   SetCollision(bActive,,);
}


/*simulated function Timer()
{
   Log("We're Being Globally Timed and are in state: "$GetStateName(), 'ELadder');
   SetTimer(0.0, False);
}*/



/*simulated function PostBeginPlay()
{
   Super.PostBeginPlay();
   //Initially disabled - gets overridden with state changes
   Disable('Tick');

   //Client goes to client state - Not here, SetInitialState about to be called..
   if(Level.NetMode == NM_Client)
   {
      Log("Going To State AutoNomous and are in state: "$GetStateName(), 'ELadder');
      GoToState('AutonomousClientState');
      SetTimer(1.0,True);
   }
}
*/


//Called after PBPlay()
simulated event SetInitialState()
{
   //So it's still visible in ed.
   Texture = None;
   bScriptInitialized = true;
   //ClientState
   if (Level.NetMode == NM_Client)
      GoToState('AutonomousClientState');
   /*if( InitialState!='' )
      GotoState( InitialState );
   else
      GotoState( 'Auto' );*/
}




/*/only called if relevant and not bNoDel.
simulated function PostNetBeginPlay()
{
   Super.PostNetBeginPlay();
   Log("PostNet BP called, we are in state: "$GetStateName(), 'ELadder');
}*/

//Called if bCollideActors
function Touch( actor Other )
{
   //Log("We're globally touched", 'Eladder');
   if( PlayerPawn(Other) != None)
   {
      //StandAlone, Listenserver host
      if (Level.NetMode == NM_StandAlone || NetConnection(PlayerPawn(Other).Player) == None)
      {
         AppendTempKeyBinds();
      }
      Other.Velocity.X = 0.0;
      Other.Velocity.Y = 0.0;
      //Not falling
      Other.SetPhysics(PHYS_Flying);
      //This is to allow using forward/backward to move up/down with respect to viewrot.
      //Eg. as if spectating, but with xy movement capped to climbradius.., unlike CheatFly, this does not ignore takedamage.
      Other.GoToState('PlayerFlying');
      //Check if has Walk anim.
      if (Other.HasAnim('Walk'))
         Other.TweenAnim('Walk', 0.1);
      //SkeletalChars don't have weaponless 'walk' anim (bug)
      else if (Other.HasAnim('WalkLg'))
         Other.TweenAnim('WalkLg', 0.1);
      //Override native falling physics update on simpawns..
      Pawn(Other).bCanFly = True;
      //Pawn(Other).airSpeed = ClimbSpeed;
      //Start Ticking
      Enable('Tick');
   }
}

//Main Tick
function tick(float DeltaTime)
{
   local PlayerPawn pp;
   local vector v;
   local float f;
   local byte b;

   //Log("We're globally Ticked!", 'ELadder');
   foreach TouchingActors(class'PlayerPawn',pp)
   {
      //Count touching players
      b++;
      //Not You.
      if (PP.Health <= 0)
      {
         eResetPhys(PP);
         return;
      }
      //We can't use bpressedjump, is not an input button & set through exec func, either stays true or gets reset depending on state..
      //Log("PPawn's aUP, bpressedjump & bduck are: "[email protected]@PP.bDuck, 'ELadder');
      //Duck's an input
      if (PP.bDuck == 1)
      {
         PP.Velocity.Z = -1*ClimbSpeed;
         //Reset bPressedJump if pressed duck
         //PP.bPressedJump = False;
      }
      //Server
      else if (Level.NetMode == NM_DedicatedServer)
      {
         if(PP.bPressedJump)
            PP.Velocity.Z = ClimbSpeed;
      }
      //StandAlone, ListenServer Host
      else if (PP.bExtra3 == 1)
      {
         PP.Velocity.Z = ClimbSpeed;
      }
      //We must reset this here, as it doesn't get reset when PP stops pressing this in his playerfly state..
      //we could also have duck reset this, so pp can press jump only once to move up, and duck once to stop..
      //PP.bPressedJump = False;


      f = Abs(PP.Velocity.Z);
      //not checking if vel<=ClimbVel.Flag to allow small movements/slides up/down when trying to jump off
      if (f > ClimbVelocityFlag)
      {
         //Moving up/down, keep player within climbradius, and cap Playerfly speed
         if (!bMoveFreeAtEnds || Abs(PP.Location.Z - Location.Z) < CollisionHeight - 2.0*PP.CollisionHeight)
         {
            v.X = PP.Location.X - Location.X;
            v.Y = PP.Location.Y - Location.Y;
            //v.Z = 0.0;
            //No Sqrt..
            //if (VSize(V) > ClimbRadius)
            if (v.X*v.X +v.Y*v.Y > ClimbRadSquare)
            {
               v = Normal(v)*ClimbRadius + Location;
               v.Z = PP.Location.Z;
               PP.Velocity.X = 0.0;
               PP.Velocity.Y = 0.0;
               //Where do you think You're going?
               PP.SetLocation(V);
            }
         }
         //Shouldn't be necessary..
         if (!PP.IsInState('PlayerFlying'))
            PP.GoToState('PlayerFlying');
         //"..either
         if (PP.Physics != PHYS_Flying)
            PP.SetPhysics(PHYS_Flying);
         //Only play climbsound when we're climbing..
         if (AmbientClimbSound != None && PP.AmbientSound != AmbientClimbSound)
            PP.AmbientSound = AmbientClimbSound;
         //bduck can override this in some states.. (eg. cheatfly)
         if (f > ClimbSpeed)
            PP.Velocity.Z = FClamp(PP.Velocity.Z, -1*ClimbSpeed, ClimbSpeed);
      }
      else
      {
         //Don't change if not configured..
         if (AmbientClimbSound != None && PP.AmbientSound == AmbientClimbSound)
            PP.AmbientSound = None;
      }
      //Check for walk anim (most should have this)
      if (PP.HasAnim('Walk') && PP.AnimSequence != 'Walk')
         PP.LoopAnim('Walk');
      //SkeletalChars..(missing 'walk' anim bug)
      else if (PP.HasAnim('WalkLg') && PP.AnimSequence != 'WalkLg')
         PP.LoopAnim('WalkLg');
      //AnimRate by speed;
      PP.AnimRate = f/ClimbSpeed;
      //Doesn't really fit..using walk
      //else if (PP.GetAnimGroup(PP.AnimSequence) != 'Waiting')
         //PP.TweenToWaiting(0.2);
   }
   //No Players, disable until next touch
   if (b==0)
      Disable('Tick');
}

function UnTouch( actor Other )
{
   //Log("We're globally UnTouched", 'ELadder');
   
   //Reset
   if( PlayerPawn(Other) != None)
   {
      //Quit walk anim
      Pawn(Other).TweenToWaiting(0.1);
      eResetPhys(Pawn(Other));
   }
}


//Reset Physics & State..
function eResetPhys(Pawn P)
{
   //StandAlone, Listenserver host
   if (Level.NetMode == NM_StandAlone || NetConnection(PlayerPawn(P).Player) == None)
   {
      RemoveTempKeyBinds();
   }
   if (P.bDeleteMe) return;

   //Make sure this is reset..
   if (P.bCanFly)
   {
      P.bCanFly = False;
      P.SetPhysics(PHYS_Falling);
      P.Velocity = vect(0,0,0);
      P.Acceleration = vect(0,0,0);
      P.BaseEyeHeight = P.Default.BaseEyeHeight;
      P.EyeHeight = P.BaseEyeHeight;
   }

   if (P.Health > 0)
   {
      if ( P.Region.Zone.bWaterZone && P.PlayerRestartState == 'PlayerWalking')
      {
         if (P.HeadRegion.Zone.bWaterZone)
            P.PainTime = P.UnderWaterTime;
         P.setPhysics(PHYS_Swimming);
         P.GotoState('PlayerSwimming');
         return;
      }
      if (P.PlayerRestartState != '')
         P.GoToState(P.PlayerRestartState);
      else
         P.GotoState('PlayerWalking');
   }
}

//State for autonomous clients (non-simpawns) - these are ought to manage their own anims..(eg. not rep'd)
//Adding bpressedjump hax - necessary to Track jump button pressings.
//Without this, player will keep ascending when pressed jump, until manually reset (eg through duck check)
//This has nothing to do with viewrot dependant vertical movement through forward/backward.
simulated State AutonomousClientState
{
   /*simulated function BeginState()
   {
      Log("We're beginning!", 'ELadder');
      //Log("", 'ELadder');
      //Initially disabled - no state code exec'd yet
      //Disable('Tick');
      SetTimer(5.0, True);
   }
   Simulated Function Timer()
   {
      //Log("We're being timed!", 'ELadder');
      Log("We're in state: "$GetStateName(), 'ELadder');
      Log("LocalPP is: "$LocalPP, 'ELadder');
      if (LocalPP != None)
         Log("LocalPP in state: "$LocalPP.GetStateName()$", with phys: "$LocalPP.Physics, 'ELadder');
   }*/
   simulated singular function Touch(Actor Other)
   {
      //Log("we're Touched!", 'ELadder');

      //If it's the local autonomous player, enable tick..
      if (PlayerPawn(Other) != None && ViewPort(PlayerPawn(Other).Player) != None)
      {
         //Reference
         LocalPP = PlayerPawn(Other);
         AppendTempKeyBinds();
         //Walk Anim
         if (Other.HasAnim('Walk'))
            Other.TweenAnim('Walk', 0.1);
         //SkeletalChars..
         else if (Other.HasAnim('WalkLg'))
            Other.TweenAnim('WalkLg', 0.1);
         Enable('Tick');
      }
   }
   simulated singular function UnTouch(Actor Other)
   {
      //Log("We're UnTouched!", 'ELadder');

      //If it's the local autonomous player, disable tick..
      if (PlayerPawn(Other) != None && ViewPort(PlayerPawn(Other).Player) != None)
      {
         //Quit walk anim
         PlayerPawn(Other).TweenToWaiting(0.1);
         Disable('Tick');
         RemoveTempKeyBinds();
         //Not necessary
         LocalPP = None;
      }
   }
   simulated function Tick(float dt)
   {
      local vector v;
      local float f;

      //Log("We're Ticked!", 'ELadder');
      If(LocalPP != None)
      {
         //Not You.
         if (LocalPP.Health <= 0)
         {
            RemoveTempKeyBinds();
            Disable('Tick');
            return;
         }
         /*/Obsolete - using keybind instead
             if(LocalPP.bDuck)
                bPressedJump = False;
         */
         //Haxor - measuring input from jumpkey
         LocalPP.bPressedJump = (LocalPP.bExtra3==1);

         //Doing this clientside as well for smoother result..
         f = Abs(LocalPP.Velocity.Z);
         //not checking if vel<=ClimbVel.Flag to allow small movements/slides up/down when trying to jump off
         if (f > ClimbVelocityFlag)
         {
            //Moving up/down, keep player within climbradius, and cap Playerfly speed
            if (!bMoveFreeAtEnds || Abs(LocalPP.Location.Z - Location.Z) < CollisionHeight - 2.0*LocalPP.CollisionHeight)
            {
               v.X = LocalPP.Location.X - Location.X;
               v.Y = LocalPP.Location.Y - Location.Y;
               //v.Z = 0.0;
               //No Sqrt..
               //if (VSize(V) > ClimbRadius)
               if (v.X*v.X +v.Y*v.Y > ClimbRadSquare)
               {
                  v = Normal(v)*ClimbRadius + Location;
                  v.Z = LocalPP.Location.Z;
                  LocalPP.Velocity.X = 0.0;
                  LocalPP.Velocity.Y = 0.0;
                  //Where do you think You're going?
                  LocalPP.SetLocation(V);
               }
            }
            //if (!LocalPP.IsInState('PlayerFlying'))
               //LocalPP.GoToState('PlayerFlying');
            //if (LocalPP.Physics != PHYS_Flying)
               //LocalPP.SetPhysics(PHYS_Flying);
            //Only play climbsound when we're climbing..
            if (AmbientClimbSound != None && LocalPP.AmbientSound != AmbientClimbSound)
               LocalPP.AmbientSound = AmbientClimbSound;
         }
         else
         {
            //Don't change if not configured..
            if (AmbientClimbSound != None && LocalPP.AmbientSound == AmbientClimbSound)
               LocalPP.AmbientSound = None;
         }
         //Check for walk anim (most should have this)
         if (LocalPP.HasAnim('Walk') && LocalPP.AnimSequence != 'Walk')
            LocalPP.LoopAnim('Walk');
         //SkeletalChars..(missing 'walk' anim bug)
         else if (LocalPP.HasAnim('WalkLg') && LocalPP.AnimSequence != 'WalkLg')
            LocalPP.LoopAnim('WalkLg');
         //AnimRate by speed;
         LocalPP.AnimRate = f/ClimbSpeed;
      }
   }
BEGIN:
   //Initially Disabled
   Disable('Tick');
   //Log("We have Begun!", 'ELadder');
   //Set ClimbRad on client if bNoDelete, after collision is rep'd
   if (ClimbRadius ~= 0.0)
      ClimbRadius = 0.8*CollisionRadius;
   ClimbRadSquare = ClimbRadius * ClimbRadius;
}

//Temporary Appending an unused input button to the player's Jump Key to keep track of continuous button pressing as well as unpressing.
simulated function AppendTempKeyBinds()
{
   local int i, j;
   local string KeyName;
   local string KeyBind;
   local PlayerPawn LocalPlayer;

   //Log("AppendTempKeyBinds called", 'ELadder');
   if (LocalPP == None)
      LocalPP = GetLocalPlayer();
   if (LocalPP == None)
      return;
   //Iterate through all keyboard keys (standard)
   for(i=0; i<255; i++)
   {
      //Get name of this button
      KeyName = LocalPP.ConsoleCommand("KeyName "$i);
      //Check what's bound to it
      KeyBind = LocalPP.ConsoleCommand("KeyBinding "$KeyName);
      //Case insensitive search if this is a jump key
      //Make sure it doesn't have extra input already (eg. player crashed/disconnected while climbing,...)
      if (InStr(Caps(KeyBind), "JUMP") != -1 && InStr(Caps(KeyBind), "|BUTTON BEXTRA3") == -1)
      {
         //We're not overwriting anything, just appending our temp input button to whatever was bound to this key
         //Use custom casing to be able to detect ours (Though highly unlikely, player might have this bound already by/for something else)
         if (right(KeyBind,1) ~= "|")//Shouldn't be
            KeyBind = Keybind$"bUtToN BeXtRA3";
         else
            KeyBind = KeyBind$"|bUtToN BeXtRA3";
         //Bind it
         LocalPP.ConsoleCommand("Set Input "$KeyName@KeyBind);
      }
   }
}


simulated function RemoveTempKeyBinds()
{
   local int i, j;
   local string KeyName;
   local string KeyBind;
   local PlayerPawn LocalPlayer;

   //Log("RemoveTempKeyBinds Called!", 'ELadder');
   if (LocalPP == None)
      LocalPP = GetLocalPlayer();
   if (LocalPP == None)
      return;
   //Iterate through all keyboard keys (standard)
   for(i=0; i<255; i++)
   {
      //Get name of this button
      KeyName = LocalPP.ConsoleCommand("KeyName "$i);
      //Check what's bound to it
      KeyBind = LocalPP.ConsoleCommand("KeyBinding "$KeyName);
      //Case sensitive search for our temp keybind
      j = InStr(KeyBind, "|bUtToN BeXtRA3");
      if (j != -1)
      {
         //Remove our temp input button wherever found
         KeyBind = Left(Keybind,j)$Mid(KeyBind,J+15);
         //Restore Bind
         LocalPP.ConsoleCommand("Set Input "$KeyName@KeyBind);
      }
   }
}

simulated final function PlayerPawn GetLocalPlayer()
{
   Local PlayerPawn PP;

   Foreach AllActors(class'PlayerPawn', PP)
      if (ViewPort(PP.Player) != None)
         return PP;
   Return None;
}

//bHidden is false to rep. collision (could be triggered)
defaultproperties
{
bNoDelete=True
bHidden=False
bActive=True
bMoveFreeAtEnds=False
ClimbVelocityFlag=7.0
ClimbSpeed=140.0
bCollideActors=True
Texture=S_Trigger
RemoteRole=ROLE_SimulatedProxy
}
[/spoiler]

There is one small issue: should a player disconnect/quit/crash while climbing, he'll end up with an extra input button appended to his jump/crouch keys, which is quite...nothing. These will be detected & removed next time he does a succesful climb :P. I'm not gonna mesh with spawning stuff in a Player's entrylevel to fix this small issue, besides, that won't survive a crash either.

Note: Even though I tested this thing quite thoroughly, I won't be using this anytime soon. So let me know should you find any other bugs.

EDIT: adding Smokegenerator code:

[spoiler]

Code: Select all

//==================================================================================================================================================
// ESmokeGenerator
//==================================================================================================================================================
// About: The Stock UT Smoke Generator exists on the server only. When triggered, the smokegen. will spawn effects serverside. Each effect is then
// replicated to a client if it is relevant to him/her (eg. can be seen). This smoke generator, when activated, replicates itsself to the client
// it is relevant to, instead of each effect individually, while spawning the smoke effects clientside, saving replication. If a stock
// SmokeGenerator is placed in a SkyZone, it can never function online, unless it was assigned a generationtype that is bAlwaysRelevant. When
// activated, this smokegenerator will check the zone it resides in to manually set its own bAlwaysRelevant=True, again replicating only
// itsself to the clients & keeping the smoke spawns completely clientside. When InActive, this SmokeGen. exists on the server only.
//==================================================================================================================================================
// Added one extra bool bForceRelevance: if true, smokegen. will be AlwaysRelevant when active. This is meant for smokegenerators that are
// supposed to be relevant to the client (active), even though the client has no line of sight to them (eg. generator is hidden in a pipe).
// Note that for skyzone smokegens, this is already done automatically. This smokegenerator is triggered, thus requiring interaction from server
// to client. Constant non-triggered smoke should be kept completely clientside without any replication (eg. a bNoDelete clientside smokegen.).
//==================================================================================================================================================
class ESmokeGenerator extends Effects;


var() float SmokeDelay;      // pause between drips
var() float SizeVariance;      // how different each drip is
var() float BasePuffSize;
var() int TotalNumPuffs;
var() float RisingVelocity;
var() class<effects> GenerationType;
var() bool bRepeating;
var() bool bForceRelevance;

var int i;


replication
{
   //Has to be replicated to clients initially..
   reliable if (Role==ROLE_Authority && bNetInitial)
      SmokeDelay, SizeVariance, BasePuffSize, RisingVelocity, GenerationType;
}

function PreBeginPlay()
{
   //Replacement..
   if (SmokeGenerator(Owner) != None)
   {
      SmokeDelay = SmokeGenerator(Owner).SmokeDelay;
      SizeVariance = SmokeGenerator(Owner).SizeVariance;
      BasePuffSize = SmokeGenerator(Owner).BasePuffSize;
      TotalNumPuffs = SmokeGenerator(Owner).TotalNumPuffs;
      RisingVelocity = SmokeGenerator(Owner).RisingVelocity;
      GenerationType = SmokeGenerator(Owner).GenerationType;
      bRepeating = SmokeGenerator(Owner).bRepeating;
      bHighDetail = Owner.bHighDetail;
      bReplicateInstigator = Owner.bReplicateInstigator;
      bTrailerSameRotation = Owner.bTrailerSameRotation;
      bTrailerPrePivot = Owner.bTrailerPrePivot;
      SetBase(Owner.Base);
      AttachTag = Owner.AttachTag;
   }

   //Log("ESmokeGenerator Initialized", 'ESmokeGenerator');
   Super.PreBeginPlay();
}


//Reroute to state corresponding to netmode
Auto simulated State StartState
{
BEGIN:
   //Using bHidden to replicate activity to client..
   Texture=None;
   
   //Log("We're in Zone: "$Region.Zone, 'ESmokeGenerator');
   if (Level.NetMode == NM_Client)
      GoToState('ClientSpawning');
   else
      //Main
      GoToState('Active');
}

//Server & StandAlone state
State Active
{
   function Timer()
   {
      local Effects d;

      //StandAlone, ListenServer Host..
      if (Level.NetMode != NM_DedicatedServer)
      {
         d = Spawn(GenerationType);
         d.DrawScale = BasePuffSize+FRand()*SizeVariance;
         if (SpriteSmokePuff(d)!=None)
            SpriteSmokePuff(d).RisingRate = RisingVelocity;
      }

      //Server count remains authorative, in order to authorize disabling
      i++;

      //Disable
      if (i>TotalNumPuffs && TotalNumPuffs!=0)
      {
         //Log("Reached puff Count, getting disabled.", 'ESmokeGenerator');

         //Replicate smokegen InActivity, necessary during the 5 seconds we're still relevant to the client while actually disabled..
         bHidden = True;
         bAlwaysRelevant = False;

         //We'll become irrelevant to the client in about 5 seconds..
         if ( bRepeating )
            SetTimer(0.0, false);
         //Destroy
         else
            Destroy();
      }
   }

   //Server & standalone
   function Trigger( actor Other, pawn EventInstigator )
   {
      //Log("We're Triggered", 'ESmokeGenerator');

      //Unhide, so we can be replicated to clients seeing us
      bHidden = False;

      //Mapper wants to force Relevance
      if (bForceRelevance)
         bAlwaysRelevant = True;
      //Manually force relevance in these zones..
      else if (SkyZoneInfo(Region.Zone) != None)
         bAlwaysRelevant = True;
      SetTimer(SmokeDelay+FRand()*SmokeDelay,True);
      i=0;
   }

   //Server & standalone (can be called by a closing mover/untouching a trigger/leaving a zone, that has our tag as event)
   function UnTrigger( actor Other, pawn EventInstigator )
   {
      //Log("We're Untriggered", 'ESmokeGenerator');

      i=0;

      //Don't disable if # puff specified.
      if (TotalNumPuffs==0)
      {
         //bHidden acts as activity flag.
         bHidden = True;
         bAlwaysRelevant = False;

         //We'll be deleted on the client in about 5 seconds..
         if ( bRepeating )
            SetTimer(0.0, false);
         //Destroy
         else
            Destroy();
      }
   }
}



//The smokegenerator will only be relevant to the client while being active..
Simulated state ClientSpawning
{
   simulated function Timer()
   {
      local Effects d;

      //Log("We're Timed: "$Self, 'ESmokeGenerator');

      //bHidden gives the Activity Status on Server, replicated.
      //We have to check on bHidden, as clientside destruction because of irrelevance, will only be called
      //in about 5 seconds if we just went hiding on the server instead of destroy().
      if (!bHidden)
      {
         d = Spawn(GenerationType);
         d.DrawScale = BasePuffSize+FRand()*SizeVariance;
         if (SpriteSmokePuff(d)!=None) SpriteSmokePuff(d).RisingRate = RisingVelocity;
      }
   }
BEGIN:
   //Server's timer remains authorative - client just keeps spawning until Server is finished (bhidden=True)
   SetTimer(SmokeDelay+FRand()*SmokeDelay,True);
}



defaultproperties
{
SmokeDelay=+00000.150000
SizeVariance=+00001.000000
BasePuffSize=+00001.750000
TotalNumPuffs=200
RisingVelocity=+00075.000000
GenerationType=UnrealShare.SpriteSmokePuff
DrawType=DT_Sprite
Style=STY_Masked
Texture=UnrealShare.SmokePuff43
bMeshCurvy=False
Physics=PHYS_None
bNetTemporary=false
RemoteRole=ROLE_SimulatedProxy
bHidden=True
}
[/spoiler]
Last edited by Core on 04 Jan 2011, 16:38, edited 1 time in total.

User avatar Buff Skeleton
>:E >:E
Posts: 4173
Joined: 15 Dec 2007, 00:46

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 02 Jan 2011, 21:04

Awesome, I'll give it a shot soon :tup:
Image

User avatar Core
Skaarj Assassin Skaarj Assassin
Posts: 106
Joined: 15 Mar 2010, 17:16
Location: ../System/
Contact:

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 04 Jan 2011, 16:39

I've added the clientside smokegen code to my previous post, also found & fixed one minor bug in the ladder script that made the ladder actor invisible in ued.

Took this opportunity to change the walk anim rate as well, instead of being an arbitrary value, it is now calculated as player's speed/ladder's max ClimbSpeed. Multiply this with a fraction or use Max(,) if you find the anim rate too fast :wink: .

redeye
Banned Banned
Posts: 1393
Joined: 08 Dec 2007, 06:55

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 23 Dec 2012, 07:42

Soooo, this is supposed to be a good pack ay ? hmm will have to see about that. (you never know about these mapper people)

hah, havn't tried it yet, but will soon.
Just ban everyone

UB_
Nali Priest Nali Priest
Posts: 7960
Joined: 11 Nov 2007, 21:00

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 23 Dec 2012, 10:46

One of the best single map releases.
ImageImage

redeye
Banned Banned
Posts: 1393
Joined: 08 Dec 2007, 06:55

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 24 Dec 2012, 02:36

Nice playing this, keep up the good work.
Last edited by redeye on 14 Jan 2014, 08:01, edited 1 time in total.
Just ban everyone

redeye
Banned Banned
Posts: 1393
Joined: 08 Dec 2007, 06:55

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 26 Dec 2012, 03:50

Was or was this not one of the first 227 maps ?
Last edited by redeye on 14 Jan 2014, 08:02, edited 1 time in total.
Just ban everyone

redeye
Banned Banned
Posts: 1393
Joined: 08 Dec 2007, 06:55

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 01 Jan 2013, 05:27

ANOTHER GREAT MAP, more than a map.

An excellent experience unlike I ever played before from any game, especially from inside UT-Unreal.

I do have some critics, but is just stupid stuff in comparison to the whole level in comparison.

great job man.
Just ban everyone

User avatar Buff Skeleton
>:E >:E
Posts: 4173
Joined: 15 Dec 2007, 00:46

Subject: Re: [RELEASED] [UT] The Last Fortress - Final

Post Posted: 01 Jan 2013, 17:00

Glad you liked it :)

Glad you also picked up on the gameplay cues by treating it as a harder-than-normal map, because that's how it was meant to play. Pretty much wanted it to be as hard and action-packed as a single map could be.
Image

Previous Next

Who is online

Users browsing this forum: No registered users and 46 guests

Copyright © 2001-2024 UnrealSP.org

Powered by phpBB® Forum Software © phpBB Limited