![]() Mechstorm's Complete Map Making Tutorial or MCM for Short. Covering Mechwarrior4, Mechwarrior4:BK and Mechwarrior4:Mercs. If you have any questions feel free to drop by our Mechstorm Editor/Scripting help Forum after you have registered on our forums. |
|
Updated Jan 23 2005 ABL Scripts and commands.Welcome to part 2 of the scripting section of this tutorial, once you have understood what is going on in last chapter you are ready for the next thrilling chapter of ABL scripting. Having dealt with the layout of abl scripts we can stick to practical examples of how to control items within scripts. So have a copy of that script fromlast chapter ready if you want to try some of these ideas out yourself. The major problem for now is where to start. This is a huge section to write so lets start with custom scoring using the devteams own scoring system Step 1: Custom Scoring using the offical scoring bucketsCustom scoring is normally setup in function init; It requires no vars so it is much easier to use than most of the other stuff we will be dealing with. Using the devteams scoring bucket system it is easy to modify the way points are awarded. It is not easy to create new ways of scoring points though. Nor is it explained how best to manipulate these scoring buckets to make new scoring systems possible. If you check mechwarrior4\content\ABLScripts directory you will see miscfunc.abi which contains a list of all the common gametypes and their scoring systems. Also in the same directory you will find mw4const.abi which contains a complete list of score buckets as well as every single var the game knows about and knows how to use. This makes this script a VERY good reference tool for this chapter of the tutorial. Be sure to read through it as you read through this tutorial. you will see many new options open up to you that the abl_orders doc doesnt even mention. So will we deal only with changing the scoring systems that exist to new values. Here is a typical function that does all the scoring for you. function init; SetFlagsEnabled(FLAGS_HIDE); endfunction; You can check what each command means in the abl_orders doc but I will quicky explain the basics here. As you might have guessed the command line listed below sets the name of your new gametype. This name appears when you hit tab in the game. SetCustomBucketName("Team King of 2 Hills"); SetflagsEnabled is also covered in the abl_Orders doc as are most of the things we will be talking about. It turns flags for CTF and steal the beacon on and off. If you're playing Team attrition you would normally turn them off using this command. Trackbucket is used to track the scores as the name very nearly suggests. AddStandbuckets simple tells the games to remember kills, deaths and stuff like that. As a general rule the following lines should always exist in your custom score system. function init; endfunction; All other AddCustomBucketParameter commands can be added if you think you need them. Please refer to the abl_orders doc for information about each bucket. Remember, the values in the lines above should be changed to suit your script, the name for example will need to be changed, The SetflagsEnabled may or may not need changing. Step 2: Custom Nav pointsCustom Navpoints require several components to work. In my own gametypes eg combatzone, you just need to add the navpoints the script needs to the map and it will work. The problem most people face with a script is that the script doesn't find all the required items it needs on the actual map and so the scores and nav points don't appear in the game. This means the script has stopped due to an error. So it's important to make sure every navpoint the script needs is placed on the map and is named correctly in the script. Before I continue I'd like to encourage you to use the comments eg // to list all required items scripts will need at the top of your scripts. Take a look at my combatzone or Team king of 2 hills script and you will see how I have done it. This makes it easy for map makers to see what nav points are required and add them to their maps. So lets gets started shall we. Lets assume we have 3 custom nav points we want to add to a map. navtom navdick and bigbetty (I would not want you to think that nav must be in every name<G>) In the map editor we open resources and go to misc, then we pick navpoints and place 3 on the map. We then rename them to Navtom Navdick and bigbetty. This will be all the navpoints our script will use in this example. Next we need to setup a script to make use of those navpoints. In the Var section of our script we write static ObjectID navtom; Next we move on to the functions section of our script. In the functions section we need to get the script to understand what those names will mean,We do this like so... navtom = ena_navtom; ENA_ tells mechwarrior this is a navpoint, you will find this explained in the abl_orders doc. Now the script knows navtom and the others are navpoints we don't have to use the full name to reference them. we can simply put navtom or what ever. So you could just use ena_navtom and that should work, the way the XXX_varname works throughout the abl script you will write means it is probably better if you use the full name eg ena_bigbetty. You could in theory do away with the var's this way completely but I find having the names as vars has avoided unexplained error messages in the past, so I enter the var's and function bits out of habit to avoid seeing these errors now. Now the script knows about the navpoints we move on to the Startstate. We can now reveal one or all the navpoints or we can wait and have the navpoints revealed to the player after he achieves an objective if we wish. In your startstate enter the following. RevealNavPoint(ena_navtom); All three of these navpoints will now be visible in the game to the player, but lets make sure he goes to Navtom as soon as the game starts. We do this in the startstate like this. SetNavpoint(ena_navtom); Or for teamgames we can set a different navpoint for each team like so. TeamSetNav(1,ena_navtom); Navtom will now appear as the first waypoint the player or team 1 sees. Thats what the 1 is for btw, its team 1. Free for all games would use the first option, team games would use the second. Thats all you need to make custom navpoints work. Team games require a little extra effort but the basic idea is the same. General Tip: A word of warning though about naming navpoints. Scripts dont like spaces in the name so calling a navpoint "Nav Center" won't work in your script. Guess what the default name for that nav point contains, yup a space. This means you will have to create your own navcenter without a space. Also avoid using the minus sign, the script will try and take nav from center and when it cannot work out how to do the math on that you will get an error. This is true for all names that contain a minus sign. Step 3: Creating 2 teams in your scripts.For those of you interested in using team based gametypes, knowing how to create a team could be handy for you. Just like the Navpoint system above several entries in your script will need to be added. You could add the parts of this step to the script you made for the navpoints and a script with custom name points for 2 teams. There's no reason why adding teams to your script should be a problem just because the script already contains navpoints. Lets start in the Var section. Add the following lines. static integer Team1; Now lets move to the functions section of your script. Add the following lines under functions. Team1 = TeamObjectID(1); TeamObjectID(1) is the real name for team1, the number changes to match the team so an 8 team game would include an entry for team 8 that looked like this TeamObjectID(8). You can refer to Team1 as Team1 or TeamObjectID(1). Depending on where you use Team1 this should work. Now in the Startstate we just enter stuff we will need, that depends on what you are trying to do. What you have already added to your script is enough to make the script recognise that 2 teams exist and allow you do things to those teams within the script. General Tip: Using any kind of var inside an abl command as an argument will lead to bugs creeping into your script. Some commands will accept the var, others won't. The problem is, we don't have a list of those that do work and those that don't. Lets quickly look at some practical examples of how teams are used in scripts. Do not try adding these to your own script. I am just going to show you how the teams can be used with other commands. if ((Team1_In) == false) then As you can see in the example about a var called Team1_In is used safely inside an if/then statement in the first line. This is always safe to do so don't worry about. If we then move to the second line we see the command iswithin is present and the TeamObjectID(1) is used to describe the team instead of simply team1, but right next to it is 2 var's, Team2Hill & radius. Confusing ain't it. Well Radius is a number set in functions and a var declared in the var section of your script. Team2hill also has a mention under the var section and in functions but unlike the teams there is no built in command that names team2hill or radius. They were invented by me which leads me to believe that is the reason they work but this changes from command to command. This approach will not always work as bugs still exist in the abl commands. That one tiny problem took me 2 months to figure out. I had thought I was doing something wrong until I spotted the var working in one command and failing in another within the same script. Here is a working example of Addpoints using the var and not causing the error mentioned above. if ((Team1_Score_Holder) < 20) then Never use a Var as a replacement for the 20 points, this does cause problems. It is a known example that appears to work but triggers a bug that gives the team thousands of points per second when you just want to give them 20 points. The Trans line we will cover next but before we do notice the first line starting with the word if and ending with then does not have a semi colon at the end. Also notice that the if statement ends with an endif statement does have a semicolon at the end. Like FSM, Functions & States, If commands must be closed using the endif command. Step 4: Using the Trans command to move about your script.If you're familiar with the old basic goto command then you can think of the trans command as a goto statement. If you're not then Trans simply sends the script to another state where it executes that states content. Lets take another look at our blank script but lets use the information we learned in the navpoint section to reveal each navpoint at different times and set that navpoint on the players up at the same time. We wont place any checks in there so if we were to really use this in the game the players navpoint would be changing hundreds of times per second. fsm myscript: integer; const type var static ObjectID navtom; function init; navtom = ena_navtom; state startState; state tom; state dick; state bigbettyState; state deadState; endfsm. What's happening in the new states is this. The Startstate is found and executed but it's empty so the script moves to state tom. State Tom then reveals navtom to the player, sets navtom in the players hub and then moves to state dick using the trans command. State dick and State bigbettystate do the same but bigbetty transfers the script back to tom. Thereby making a loop. The script will now loop through all 3 states until the script is killed off by the deadstate when something causes it to move to that state, eg one of your conditions may become true and you tell it to move to the dead state. The script above should never hit the dead state because I have not told it to go there. AI Brain files automatically skip to the dead state when the object that has the script attached to it is killed or destroyed. So you have seen how to use navpoints, how to setup teams and how to score points both with the custom score buckets and via the addpoints command in one of my examples. Time to show you the sort of information usually contained within a State. Step 5: Making a new gametype.You're now ready to make your first gametype. To do this you will need to have abl_orders open and handy as you will need to look up the commands you want to use. You will need to remember how the var and functions sections work and now i will show you how the states can be used to do all the work for you. We will be using a custom score system in this too. Lets start by copying the script from above and giving it a real name. Edit the fsm name to call it waypoint_attrition like so. fsm waypoint_attrition.: integer; const type //Now we want to make sure the vars we will be using are added to
the the right section. We var static ObjectID navtom; //new bits you need to add, these are for detecting the players position in relation to the waypoint //later on. static integer Radius; //Lets tell the script about these new additions in the functions section. function init; navtom = ena_navtom; // New bits you need to add radius = 200; // we want the team in vars to be false as the player is not at the waypoint yet so we do this like so.
// Now lets setup the scoring. This is taken directly from Team attrition
without any changes except SetCustomBucketName("Waypoint Attrition");
// We need to tell it to revealnavpoints so the navpoints get revealed
before the player reaches state startState; // Now we check to see if team 1 and team 2 are within 200 meters
of the 3 different way points, state tom; if ((Team1_In) == false) then if ((Team2_In) == false) then endstate; state dick; Team1_In = false; if ((Team1_In) == false) then if ((Team2_In) == false) then endstate; state bigbettyState; if ((Team1_In) == false) then if ((Team2_In) == false) then endstate; state deadState; endfsm. The above script is starting to look a little complex now, but there's nothing in it you have not already read in other parts of this tutoral except how the if/then lines work. So lets talk you through one State so you can see how all the other states also work. Believe it or not, they're identical, only the navpoint names have changed. Lets break State tom down/ state tom; We make sure both Team1_in and Team2_in are false at the start of this state because we will be setting them to true later in this state and unless we change them back we will have serious problems, the reason being the script remembers the previous value which in the case of newly entered states will be the same as the value from the previous state. Which is true normally but we need it to be false at the start of these new states. So we set them to false now. Read below for more details on the reasons behind this. Team1_In = false; I have added team1_in = false to the TOM state even though we don't need to in the first state, remember we set these to false in functions and it has not been changed yet. It will not affect the script if we repeat it and I want you to remember we have made sure that the Team1_in var is being reset to false at the start of each new state the script enters. If we don't then every state after this will find Team1_in is automatically true and it should not be. The result would be the player sees the waypoints cycling through very quickly and each time they do, 100 points will be added to the teams score, which is not good at all. So setting it to false basically says, do not change the waypoint and do not add 100 points to the score YET. Remember Team1_in asks if Team1 is within 200 meters of navtom. If they are not then it's false. We always assume they are not by adding the Team1_in = false line to the very start of each state. This is the logical way you must think when writing scripts. This means Team 1 is not at navtom yet. We change this to true when they reach navtom. The first two lines below do this for us, the third line changes Team1_in to true thereby allowing the script to reveal the next waypoint. The line after that changes the waypoint on the players hub, the addpoints line then gives him 100 points. Finally it transfers to the next state. If Team1_in is false, meaning the team is not near navtom, then none of that will happen. The script simply goes back to the start of state tom and checks to see if team1 has reached navtom yet. Looping around and around until it is true and we allow it to do all the stuff explained above. This is the Boolean var in action (Team1_In is our boolean var). You can see how powerful it is in this example. See Chapter 6 for an explanation of the Boolean var. if ((Team1_In) == false) then When we get to Team 2 we are doing exactly the same thing as we did for team1. No changes except we are doing it for team2 now and not team1. if ((Team2_In) == false) then endstate; Take some time to study this script. It should be complete so it would actually work as a gametype but it may contain some minor errors as I have not actually tested this out myself. The logic behind the script is sound and the system I have used here is one I have used before. So I know this idea works and is easy to do. Most of it involves cut copy and pasting states, then changing the team names and state names. So it may look like I typed a lot out but I have not. Step 6: Learning how the commands in ABL_Orders workYou have now seen what makes up a typical abl script and seen how a simple Boolean var can be used to detect if a player is near a navpoint and how to change it. You could add to this by placing a command like chatmessage before the Trans lines in the states that control the navpoints. Like adding this line before Trans dick, Trans tom and Trans bigbettyState chatmessage("Team 1 has reach a Navpoint"); or for team 2 chatmessage("Team 2 has reach a Navpoint"); The message can be anything, you can make a different message for each navpoint if you like. The number of actions you can do within each state is only limited by the commands available for you to use. This means I cannot teach you anything else. From now on you will have to study the abl_Orders to learn how other commands can work within this system. You can do a lot with the commands available to you if you spend the time to learn them. What's even better, is the AI Brain files will be a walkover for you now. You can use the tips I have placed in this chapter to avoid the problems I faced and use your newfound skill inside an AI brain file to make the AI appear to be more than just a list of skill settings. You could edit the AI using a script based on the information I have shown you above. AI Brain files do not normally use scripts in this way but most of the commands work better in an AI Brain file than they do in gametypes. So adding chatmessages and navpoint data to a AI Brain file should still work. The big difference is, if you check to see if team1 is at a navpoint in an AI brain file, you won't be giving the team any points or changing their waypoints, you would be using it as a trigger to tell the Bot it's time to attack or to move to a new location. The principle is the same, you use Var's, functions and states in exactly the same way for AI Brain files as you would for gametype scripts. So the next Step in this tutorial which covers AI Brian files is really only there to catch the people that didn't read the rest of this chapter. Everything you need to know has been shown to you and everything you will use to make your scripts work is in the Abl_Orders doc that comes with the Editor. However, for those that want to brush up on their AI Brain files, we will cover this in the next chapter. Once you have finished, run check scripts from the Mission Editor to make sure your script is error free. Step 7: Using Locpoints & Teleports[Thanks to Ash for supplying this information]Ash kindly posted a script that allows me to explain the process of setting up locpoints and use of the teleport command. To follow these instructions you will have to already know about navpoints and how to set them up and use them from within scripts. This is a key skill in this part of the tutorial. First thing you have to do is declare the vars you want to use, you will also probably have to declare your nav point names, but thats already been explained else where in this tutorial so I'll simply paste in the commands here. var's static ObjectID ai_startpoint; // our navpoint static locpoint teleport_location; // our locpoint Now we have our vars setup we need to tell the script what they mean. We do this in the function init section like so. my_ai_startpoint = ena_ai_startpoint; // telling the script our navpoints full name is..... I do not think theres a label to use for locpoints so I doubt we will need to declare those in functions. So lets skip to our states. The following command just makes our locpoint share the same coordinates as our navpoint. By setting our locpoint to match our navpoints in this fashion we can use a navpoints real location as the final location of our locpoint are using the command below. getlocation(ena_ai_startpoint,teleport_location); As you can see, the command simply says teleport_location is at exactly the same spot as ena_ai_startpoint. Pretty clever really (Ash). You can use the getlocation command to return the location of any object on the map just by replacing the navpoints name above with the name of the object. So if you want the locpoint to be a dropship that needs to be defended, you simply enter the dropships name in place of the navpoints name. It works the same way, it mearly sets the locpoint to the location of the dropship. Straight forward stuff really. Now we have set our locpoint to our navpoint (which we placed on
the map using the editor), we know exactly where our unit will appear
if we teleport it. If we add the following command to an AI brain
file then that unit will teleport to our locpoint which is ena_ai_startpoint
as soon as the script reaches the command. teleport(me,homingbeacon); Where ME means the AI that has this Brain file attached to it. The option ME should not be used in gametype scripts. If your refering to a unit in a gametype script you must use the units full name. Ash used these commands in a slightly different way, I will show because it's a good example of how you can combine commands such as this in different ways. switch (getmemoryinteger(me,0)) case 1: case 2: case 3: case 4: case 5: As you can see, Ash uses the full name of the navpoints there by removing the need to have an entry in the var section. His locpoint is homingbeacon and he uses the memory cells of an AI unit to switch the location of the locpoint depending on events that happen in the game. You can read up about Memory cells in the AI Brain file section. The locpoint and teleport system should work anywhere from AI brain files to gametype scripts, though you will have to be careful how you call your units as ME wont work from a gametype script but will from within an AI Brain file.
|