The Infinity Blade Forums Have Moved

We've launched brand new Infinity Blade forums with improved features and revamped layout. We've also included a complete archive of the previous posts. Come check out the new Infinity Blade forums.
See more
See less

Character Movement

  • Filter
  • Time
  • Show
Clear All
new posts

  • Character Movement

    I've tried searching the forum for this and apparently the search function is down at the moment so my appologies if there is another subject on this.

    I'm trying to figure out how to add new moves to my pawn.
    After following! I now have a robot running around in third person view.
    I cannot get it to crouch whough I've set bCanCrouch=true in my custom PAWN.uc-file.

    After viewing PlayerInput.uc I learned I can exec 'jump' from the console - and then the robot jumps. However there is no equalivent for 'crouch' or 'duck'.
    So I'd like to hear some insight on how to make the character crouch.

    Anyway. I want to add more moves to my robot than just crouch. Like Sprint.
    And if you're familiar with Warsow then you might know what a 'dash' is. If not, it's a secondary jump function best described as a very quick step into a given direction.

    The question I have is how can I add new moves like a secondary jump function?
    I mean so that I can bring down the console and exec 'jump2' etc and actually see this happening the same way that the ordinary 'jump' is executed.

    I tried adding:

    exec function Jump2()
    if ( WorldInfo.Pauser == PlayerReplicationInfo )
    SetPause( False );
    bPressedJump2 = true;

    to my custom PlayerInput.uc just to see if a command like 'Jump2' could be executed, though such a function isn't defined elsewhere, rebuilding the scripts tells me "Error, 'bPressedJump2' : Bad command or expression"

    And only:

    exec function Jump2()


    didn't add an exec command for a jump2 function. I guess I have to define a function like 'jump2' elsewhere in order to make it work.

    I can always tweak it later with a "JumpZ=+X.X" etc. under "defaultproperties" in my custom PAWN.UC-file later on. Question is, how can I copy/paste the jump-function to a jump2-function?

  • #2
    Jump Script

    I've managed a very basic, tidy little Jumpscript here.
    It handles a basic jump and a basic crouch.
    Not much of a contribution but if anyone want something like this it might save you some time.

    This goes in your Pawn File.
    function bool DoJump( bool bUpdating )
    	if (bJumpCapable && !bIsCrouched && !bWantsToCrouch && (Physics == PHYS_Walking))
    		bDodging = false;
    		Velocity.Z = JumpZ;
    		AirControl = DefaultAirControl;
    	return false;
    This goes in your PlayerController File.
    function CheckJumpOrDuck()
    	if ( bPressedJump )
    		Pawn.DoJump( bUpdating );
    	if ( Pawn.Physics != PHYS_Falling && Pawn.bCanCrouch )
    		Pawn.ShouldCrouch(bDuck != 0);


    • #3
      Exec functions only work in certain classes such as GameInfo, PlayerController, and a few others.


      • #4
        Hmmm... I'm not surprised.
        I even believe it's hard to drawl values from classes unless they are from the same line of extensions. Still, I have this stamina bar running in PlayerControll, and I can't get my Pawn to use it in anyway.
        I don't know if it's possible to connect variables from other classes or not. Sometimes it works, sometimes it doesn't. :S
        I end up simulating functions from one class inside another to make them at least seem like they are working together. xD
        This is just lack of understanding talking. At this moment I'm trying to figure out a way so that my Pawn can understand "bPressedJump" the same way that my PlayerController does. By the way, do you know if there perhaps is a way to create a Bool Var from 'Jump' that works in a similar way that "bDoubleJump" does?
        That would, in fact, be very useful to have.


        • #5
          Try googling some tutorials on Object Oriented programming. In my experience a lot of newcomers don't have this basic knowledge which underpins everything. Once you get the basics of OOP you won't have any troubles accessing vars.

          It's not easy to sum up in a single post, but I'm bored so here goes...

          Classes define a template, or blueprint, consisting of properties (variables) and methods (functions) which together makeup the members of the class. This template is used to produce objects through a process called instantiation (Spawn for actor type classes).

          Are the real, tangible instances of a class. Individual instances of objects can hold different data. Instances of an Actor class can have different Location and Rotation values, for example.

          The difference
          Consider the class as an asset, and an object as a 'living copy' of that asset. Whereas the class defines variables and functions, it's the object that actually holds the values of those variables and executes the functions. A single class can be used to produce many objects.

          The pitfall
          The biggest mistake when learning OOP is to think of your game world as a collection of classes. They are objects. The class defines their properties and behaviour. Your player, his weapon, that missile, the explosion, the score printed on the HUD... objects, whose type is the class that defines them.

          When an object is created we need a way to address it, or reference it. The Spawn() function will create an actor in the world and return a reference to that actor, which you can store and use to access it.

          References are not instances
          A reference points to an object, but is not the object itself. The object exists in memory and you can have several references all pointing to the same object.

          When actors are spawned a reference is also stored internally. Iterators such as AllActors, AllDynamicActors, etc are searching through lists of such references.

          Types, Typecasting
          (You know what, I'm really too tired to go into this one tonight, lol)

          A reference that points to nothing. It's sometimes important to check a reference is valid before using it, and you'll see the pattern "if( reference != None )" repeated everywhere.

          Garbage Collection
          Objects live until there are no more references pointing to them. Lonely and dejected, they're embraced by the garbage collector... which puts them out of their misery by destroying them. However, remember that the engine maintains internal references to actors, so an explicit call to Destroy() is necessary for the engine to 'let go' too.

          Getting a reference
          Most classes perform a specific role within a system. PlayerController's role is to handle player control, Pawn's role is to represent the player as a physical entity. Since their roles are deeply connected they both contain references to each other. This pattern is repeated throughout the codebase for things like HUD, PlayerInput, Weapon, etc.

          So accessing the variables and functions of an object becomes a question of "who maintains the reference to that object?" For example, the PlayerController and Pawn have references to each other, but the PlayerController is the only one with a reference to the HUD. How to access the HUD from the pawn? Go via the playercontroller:

          // Accessing our CustomHUD from CustomPawn.uc...
          if( PlayerController(Controller) != None && CustomHUD(PlayerController(Controller).MyHUD) != None )
              CustomHUD(PlayerController(Controller).MyHUD).StaminaBar = 100;

          Classes can extend other classes. The parent class is called the base or super, while the new class is the derived or sub class. When a class extends another class it inherits all the qualities of the base class. Thus a variable defined in the base (or deeper down the inheritance chain) is part of the new class.

          If ClassSub extends ClassBase, then an object of ClassSub can be considered as type ClassBase as well as ClassSub. This is because ClassSub is a ClassBase. For example, Siamese extends Cat... Siamese is an object of type Siamese, but it is also an object of type Cat: Siamese is a Cat. However, a Cat object is not necessarily a Siamese object.

          The small print
          Classes are actually objects that can hold values and execute functions. But, don't tell anyone I told you that because it's very confusing


          • #6
            I kind of figured I'd learn as I go, you know.. learn by doing. I've been tampering with the UC scripts and had my "Yeah! Hail to the King!-moments"... But most of the time, I've been in the stage where I had no idea how to do anything.
            Believe me when I say, I've viewed theese codes as an infinite chaos that does nothing and everything at the same moment. In addition, the file structure of theese classes always seemed highly unlogical. So not much of it made sense to me.

            However, this post of yours helped change my perspective on this. I got some key-definitions clear to me and I can actually see the logic I knew existed here. It got interresting on a whole new level. Basicly, what I'm trying to say is that I'm very thankful for your previous post.

            Object Oriented Programming. It's good to have a name on it. So I suppose learning some OOP would be the most natural thing to do. In fact, I'm looking it up at this very moment.

            Thanks! Really!


            • #7
              Glad it helped. The example I gave for accessing the hud from the pawn may be a little confusing, because I included all the necessary typecasting and safety checks. Conceptually all it boils down to is:

              // psuedocode from Pawn
              Controller.MyHUD.SomeVariable = 100;
              Pawn's variable Controller is a reference to a controller object (could be a PlayerController).
              PlayerController's variable MyHUD is a reference to the HUD object.

              I'll briefly go over types and typecasting...

              Every object has a type - it's class - and references to objects must be typed accordingly: just like int, float and bool variables represent integer, floating point numbers and true/false values respectively.

              var Pawn MyPawn; // MyPawn is a variable of type Pawn; a reference to a Pawn object
              I explained a little about inheritance and polymorphism, and the notion that objects of a subclass can also be typed as their base class. The Siamese being a Cat in the example. This is also true of references.

              // assuming the class Siamese extends from Cat, and Cat extends from Actor...
              var Siamese MySiameseCat; // reference to a Siamese object
              var Cat MyCat; // ... to a Cat object
              var Actor MyGenericActor; // ... to an Actor object
              MySiameseCat = Spawn(class'Siamese'); // Spawn the breed of cat and assign it
              MyCat = MySiameseCat; // this also works, because Siamese is a Cat
              MyGenericActor = MySiameseCat; // and so will this, since Cat derives from Actor; Siamese are Cats and Actors
              However, a reference has scope. Scope is limited to the type (class). In the above, MyCat can point to a Siamese cat, but you cannot use it to access the properties and methods of Siamese because the Cat class has no idea what a siamese is. All it knows about are cats and actors. The same is true for MyGenericActor, whose scope is limited to Actors (and whatever else actor classes inherit).

              Importantly, the reference still points to a Siamese object. It's just that the usefulness of the MyCat and MyGenericActor references are limited in context.

              Is the conversion of a reference of one type to another type. For the cast to succeed the types must be related. Unrelated casts fail by producing a reference of None.

              MySiamese = Siamese(MyCat); // cast the MyCat reference back to a Siamese
              MySiamese = Siamese(MyGenericActor); // and again, for MyGenericActor;
              // suppose we have another breed of cat...
              MyPersian = Spawn(class'Persian');
              MyCat = MyPersian; // yes, persians are cats
              MySiamese = Siamese(MyCat);
              // FAIL - siamese are cats, but MyCat is pointing to a Persian
              // Persians are cats too, but Persian is an unrelated class to Siamese
              Throughout UDK you'll see the same thing happening, with checks and balances for None results. These checks have two purposes. They ensure that a reference points to something, because it's always possible the reference is None to begin with. And they also ensure that the object is relevant to the context in which you want to use it.

              A perfect example of this is the Controller variable in Pawn. There are two main types of controller, PlayerController and AIController. By having a reference to the more generic base class Controller the pawn solves the problem of complexity by using a single property regardless of which it is. So is it a player or an AI? Cast it and see...

              if( PlayerController(Controller) != None )
                  // pawn is being controller by a player
              One thing to note, UDK has a habit of using conflicting names. That variable Controller is of type Controller. The compiler considers this legal and it works fine - but it is really confusing at first, and to be honest it's bad practice and should be avoided.


              • #8
                This link looks quite informative and language independent, though it does get quite technical. UnrealScript is quite a simple OOP model compared to some languages.


                • #9
                  Thanks, this is all very helpful! I'm unfamiliar with most of these terms, but the detailed explanations you gave make things much easier to understand for a hypernoob of programming such as myself lol.