View Full Version : [How To] Some Basic Scar for Mappers
Sando
20th Jan 09, 10:02 AM
Hello,
There's been various useful "How To's" for scar before, but thought I'd add some additional stuff, and give you some simple examples from my code library. The purpose of this tutorial is to very quickly give you a taste of how scar works and to be using it on one of your own maps within 20 minutes of reading.
I'm assuming you already know the basics of world builder and how to create a new custom map. I'm not assuming you know very much about coding, or how to create various file types.
Why Scar?
Scar code is a very powerful tool for changing how your map works, and possibly change it into a full blown scenario. Even a very quick and easy scar file can radically alter how your map plays.
Scar allows you to modify your map in ways which World Builder simply cannot, and even add an intro, a storyline or a series of objectives to it. This can be for multiplayer, co-op or single player modes.
Creating a Scar File
Creating a scar file is easier than you probably think, you don't need any special software (although it can be useful for debugging) and I'd recommend you use windows notepad to start with - you can find it in START | Programs | Accessories on most PCs.
Create a new file, and do a save as. The name of your fil e needs to match exactly with the name of your custom map (as a file), add .scar on the end of it, and change the "save as type" to all files. Save it in your \Program Files\THQ\Company of Heroes\WW2\Data\Scenarios\MP folder.
Scar files are essentially a list of instructions for the computer to follow, and describe to it how to react to particular events that occur as the game plays out (this could be on a timer, or when a key territory is captured, for example).
Integrating a map with Scar
Is also easier than you might think, in World Builder (WB), click on the marker icon (the red flag in the taskbar). The marker mode sidebar will now appear. This should default to "scar markers" mode, and you will see a list of available markers (colours mostly) in the middle of the sidebar.
It also helps to click on the red flag icon on the main taskbar which has an eye, and a "ABC" next to it. This will show you your markers, and their names, even when you're not in marker mode.
These markers are what allows you to describe to the computer where you want events to take place on the map, rather than trying to hand code them along the x, y, z axis'.
WB will automatically create a file called "map_name_id.scar" when you save the map, and will automatically populate it with all your marker names and colours. You can open this file with notepad if you want to check it - be careful not to change or save it however!
Marker types - There are a few types of marker that I don't fully understand or use personally (maybe someone can fill in the detail here?). These are "custom" and "rectangle".
Basic Markers (the 1st item in the list) are special markers that allow you to spawn units (SBPSs), although they can also be used for all the functions of coloured markers (described below).
Most of the other marker types are simply colour names, and as far as I can tell, it really doesn't seem to matter which colour you use. Use the different colours for different kinds of code, to help you remember what you're using it for. For example, I tend to use Red Markers as artillery drop points, and Cyan Markers as troop movement points.
When in marker mode, simply select the kind of marker you want to add, then right click on the map to add it in the desired location. You can move these about as normal.
You'll notice that when you add a marker, it is automatically given a name, and a radius of 0 (we'll come to these another time, but leaving it as 0 is fine for now). The name doesn't really matter as long as you match it exactly in your scar file...however it will make life much easier in the long run to use a naming system of some kind.
I'd suggest something along the lines of:
s_depoteast1
s_depoteast2
s_depotwest2
Where the "s" stands for spawn (a point where units enter the battle), the middle part is a description, and the final part a number.
The first two parts help remind you of the purpose of the marker, and it's location. The number at the end can prove very useful later on the in process when you may want to randomise where troops spawn from.
***
That's all for now folks, I'll post up some further articles on how to Set Game Parameters, Spawn Troops, and add off-map abilities in the near future.
Sando
20th Jan 09, 11:23 AM
About Scar Code
Scar code uses what's called an "object orientated" style - this means that it's functions (ie. what it does) are based around "objects" (separate chunks of code). Basically this means that the functions in the code are separate, and can be written in any order - it doesn't matter too much when a function is ran, it doesn't necessarily need to be in chronological (time) order.
The two key points here are:
1) Writing these individual functions (chunks of code)
2) Linking the functions together
Hopefully that all made at least some sense to you, and becomes clearer as we progress to some examples.
Writing Code
A few basics here.
The first one is that code is by it's nature "fussy" - if there is a mistake in the code, the map will pause with a "fatal scar error" (sounds nasty!). You can press ctrl shift and ~ on your keyboard when in the game to access the console - this will describe to you what went wrong. Use the page up / page down keys to scroll, look for the section marked "FATAL SCAR ERROR" and the message next to it.
Next, each line of text must be complete, and not spread over multiple lines. Notepad can be confusing in this regard, as it automatically "word wraps" lines so you don't have to scroll right to see the entire line. You can turn this off by going to the "Format" Menu and unticking "Word Wrap".
Next up "REM"s. Basically this tells the computer to ignore whatever you've written on this line. This is very useful for adding reminders and descriptions for yourself so you can remember what a function does. COH uses "--" at the start of a line to do this.
Still with me? Again, this will hopefully make more sense when you see examples.
Some Sample Code
Ok, time to throw you in at the deep end with our first function:
function OnGameSetup()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
end
This is one of the first sections of code in any COH scar file, and a vital one. "OnGameSetup()" is a special function, which runs as soon as the map is loaded into memory when you begin a game using your custom map. It uses the same basic layout as any other function you may use.
The "function" line at the start tells the computer that you want to create a new function, the "OnGameSetup" part is it's name, and the "()" at the end is essential.
The "end" line at the bottom of the function tells the computer that the function is complete, and only lines between the start and end of the function are to be ran.
To go back to our example, the lines of code here are essential to any scar custom map -
player1 = World_GetPlayerAt(1)
Basically this tells the computer that a player exists (you need 1 line for each active player, the example x4 for a 4 player game), and names them so that you can refer easily to them later on.
***
Ok, so you got that bit...but you want to see the code actually working in action, right? In the "OnGameSetup" function, you can set various things about the players, here is a longer example:
function OnGameSetup()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
local player1name = Util_CreateLocString("British X Corps")
local player2name = Util_CreateLocString("British 2 Commando")
local player3name = Util_CreateLocString("4th Wehrmarkt Army")
local player4name = Util_CreateLocString("15th Panzer Elite")
Setup_SetPlayerName(player1, player1name)
Setup_SetPlayerName(player2, player2name)
Setup_SetPlayerName(player3, player3name)
Setup_SetPlayerName(player4, player4name)
end
In this example, we are adding some additional code that will automatically override the names of the players to the names we have provided above.
The first set of lines simply provide the computer with a "string" (a text item):
local player1name = Util_CreateLocString("British X Corps")
The next set of additional lines tell the computer to apply these names to the various players:
Setup_SetPlayerName(player1, player1name)
You can play around with this by changing the 1st "player1" part to "player2" for example - and the name set for player1 will apply to player2 instead.
This is probably a good time to talk about the "commands" (ie. the things we want the game to actually do) we are using here, and how they're laid out.
Relic has coded an enormous number of commands into the game, and you can get a complete list here. (http://files.filefront.com/scarzip/;10127667;/fileinfo.html)
We can access this vast library of commands easily through scar - I wouldn't worry about reading through any of the files at the moment, but they'll come in very useful for reference later on.
We'll break down one of the commands above further, to give you an example of how they work:
Setup_SetPlayerName ---- (player1, ---- player1name)
I've separated the line using "----" to make it easier to see the individual parts, normally they should be continuous.
The first part of the line tells the computer which command to use from the relic library. Depending on the command, you then have to provide a certain number of "variables" (how you want the command to be used) - these are the parts in brackets and these are always separated by commas.
In the example, there are two variables that need to be provided; the first one is which player the command should be applied to, and the second is what we want to set the name as.
A Working Example
If you've tried using the function listed above, you'll have found that it doesn't actually work yet. The reason for this is that we're missing one vital piece of code - the one that tells the game to import the relic library so that it has a complete code list. This always needs to be the very first item in your scar file:
import("ScarUtil.scar")
Now, how about a full section of code that you can actually try ingame?
import("ScarUtil.scar")
function OnGameSetup()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
local player1name = Util_CreateLocString("US 3rd Army")
local player2name = Util_CreateLocString("British 2 Commando")
local player3name = Util_CreateLocString("4th Wehrmarkt Army")
local player4name = Util_CreateLocString("15th Panzer Elite")
Setup_SetPlayerName(player1, player1name)
Setup_SetPlayerName(player2, player2name)
Setup_SetPlayerName(player3, player3name)
Setup_SetPlayerName(player4, player4name)
end
You can try this on any 4 player map by creating a scar file with the same name as your map file (SGB only), and then copying and pasting the code into the scar file, and launching the game in -dev mode, and running it in skirmish.
Works?
A more advanced example
Ok so you've got the player names working properly...now to try out a few of the more powerful things scar can do. Add the following lines to your scar file, between the "SetPlayerName" command and the "end".
Setup_SetPlayerRace(World_GetPlayerAt(1), 1)
Setup_SetPlayerRace(World_GetPlayerAt(2), 0)
Setup_SetPlayerRace(World_GetPlayerAt(3), 2)
Setup_SetPlayerRace(World_GetPlayerAt(4), 3)
This code will override a player's choice of army that they made in the lobby - beware however that if you then played with "random" or "reversed" map settings that the Axis players will become Allies and vice-versa! This is because the scar code will simply match up with the players numbers you assigned in WB.
Again, we'll break this code down:
Setup_SetPlayerRace (World_GetPlayerAt(1), 1)
The first part again calls the command we'd like to use from the relic library. The first variable is the player's position on the map (according to WB), and the 2nd variable tell the computer which army/race to assign to that player.
For army choices the following variables apply:
0 = British
1 = US
2 = Wehr
3 = PE
Try changing these variables around in your file and see the results ingame...
Next time out, we'll have a look at how to add another special function, plus how to make custom functions and run them. This will allow us to setup starting resources, player resource rates, preset doctrine choices and which units and structures are available. We'll also take a look at how to debug (fix!) your code.
Monkey Soldier
20th Jan 09, 1:37 PM
Thanks for the great how-to!
Celéstial
20th Jan 09, 11:52 PM
Yes, this is awesome! Thanks buddy!
sirpsychoj
21st Jan 09, 12:34 AM
Nice work Sando, It would be great if Admin could have a seperate section alone for scar, I do understand there is not that much out there and this is probably why they wouldnt consider it, but I find the search, and the assorted scattered files around are messy or outdated. A new area for Scar with people interested in it like myself could certainly make this a viable and appreciated Forum and could certainly test or say if its old Scar from previous patches. Unfortunately I had to learn the hard way like most ppl and work it out for yourselves, if this could somehow be incoporated it would be great and I would certainly upload lots of Scar files I have made from plane troop dropoffs and then planes fly away, to tunnel networks, to a complete build order for Locked AI to build up defences and perimeters where ever you want. To all different assorted triggers/actions and Mission Objectives, and at the same time, I'd also appreciate other peoples Scar with there different ideas and ways of going about things, it could save people months of relentless work and I'm sure in the long run all those interested already, and newcomers would also thouroughly appreciate it. So it could be setup with a Title which consists of version(patch) then a refrence to what the file does, eg.
Compatibility: COH/OF., version 2.301
Ref: This changes a prebuilt Axis medic bunker for PE, then upgrades it so upgrades are available for shreks/mp's and first aid kit for new squads(axis-grenadiers). Only thing that cant be done is voice changes for PE. So without listing all of them, theres many ways of putting/building the bunker, "i'll keep it the simplist for now, and you can change it to your own build setup. Open WorldBuilder and your map, place a medic bunker on spot you want, and change ownership to player1, done. Now place a Marker in same spot, name the marker mkr_medic_station and give it a radius of 10. And now copy the parts of the Scar File you need( this is where there needs to be a more understandable tutorial on setting up a Scar File)
import("ScarUtil.scar")
-- Called immediately on startup, this just sets out some parameters for the mission
function OnGameSetup()
-- set up the players
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
Rule_AddInterval(setup_medicstation, 2)
end
function OnInit()
Scar_AddInit(OnInit)
function setup_medicstation()
sg_medic_troops = SGroup_CreateIfNotFound("sg_medic_troops")
Player_GetAllSquadsNearMarker(player1, sg_medic_troops, mkr_medic_station, 10)
Cmd_InstantUpgrade(sg_medic_troops, UPG.AXIS.PHASE2, ITEM_UNLOCKED)
Cmd_InstantUpgrade(sg_medic_troops, UPG.AXIS.PHASE3, ITEM_UNLOCKED)
Cmd_InstantUpgrade(sg_medic_troops, UPG.AXIS.PHASE4, ITEM_UNLOCKED)
Player_SetAbilityAvailability(player1, BP_GetAbilityBlueprint("abilities/medical_kit.lua"), ITEM_UNLOCKED)
end
lilmat1
21st Jan 09, 1:54 AM
This is what I believe a lot of us has been waiting for.
Absolutely Fantastic guys....
I agree that...we would ask to have an area put aside particularly for scar. We so need one area to see all this, because of the fact that scar can make maps, missions so...much more in depth and interesting to play. It helps keep the interest in this great game for all well into the future.
Remember...this Community has done A LOT for this game, and not to mention all the hard work from all of the Relic team.
With time it well get better and better.
I have some scar that may help, but might wait we it can be organized a bit better.
Cheers guys...fantastic work... :beer:
Cozmo
21st Jan 09, 7:06 AM
Just an FYI, this thing (ScarDOc) is easier to use that reading all of relics scar files.
http://wombat.corsix.org/coh-scardoc/
Second, use corsix's mod studio, it has a check syntax option, and it also does auto-complete for relic made functions.
Also if you use corsix's mod studio you can take a look at relics files and they easier to read since it also has syntax highlighting. if, function, then blabla turn blue, strings turn purple and comments turn green etc.
Also Sando I'd advise teaching loops, they are fucking invaluable, less code = less errors, and easier to understand + debug.
Sando
21st Jan 09, 9:04 AM
Thanks guys - glad to see this is useful :)
I agree completely we probably have between us a lot of various pre-made code that would be very useful if pooled, got my vote for a scar forum :)
Cozmo, thanks for the link, the old one (also now not accessible from the World Builder wiki) died and I didn't have the new one.
I agree using the mod studio makes it easier, and loops are very useful (they'll be in a later post) - however, I wanted to start right at the beginning for non-coders, give plenty of explanation of what does what, and allow people to quickly get some ingame results.
I'll upload the next post soon, hopefully tonight...
Cozmo
21st Jan 09, 10:23 AM
I've made a few functions people may find useful, il upload them so people can have a look.
(It a .rar because .scar is an invalid file type)
Anyway, I made some functions that I thought relic should have put in as I found them quite useful.
They are:
EGroup_ClosestEntityToPoint(EGroup, Pos)
SGroup_FilterByUpgrade(SGroup, Upg, Filter_Type)
SGroup_ClosestSquadToPoint(SGroup, Pos)
Squad_GetSquadsHeldID(SquadID)
SGroup_FilterByIDTable(SGroup, tableID, Filter_type)
EGroup_FilterByIDTable(EGroup, tableID, Filter_type)
SGroup_GetContainedSquads(SGroup)
Util_RemoveItemFromTable(tableID, item)
The info is in the file in the same format relic did it:
--? OMG Custom Function
--? @shortdesc
--? @result
--? @args
If you don't understand what arguments one needs or what it does, ask me :).
Sando
21st Jan 09, 10:35 AM
If you've successfully worked through the previous posts, here are some more settings you can use.
Making a custom function
Custom functions can vary from simple lists of commands, to entirely new commands that you can setup.
function test1()
-- Your code goes here
end
As you already know from the previous posts, the "test1" part at the top is the name of function. You can call yours almost anything - although it must not clash with an existing function by having the same name.
Altering a Players Resource Rate
The first example here is how to change a player's resource rate. This effects how fast (or how slow) a particular resource is gathered.
First of all, resource collection will depend on how many strategic/fuel/munitions points a player controls, the resource rate is then applied to this number. For example, if a player has a HQ and one +5 fuel point, he will collect fuel at +10 per minute. (5 + 5)
If we used the example code below, the player's fuel resource rate would be reduced by half (50%), as (5 + 5) * 0.5 = 5. If they then captured another +10 fuel point, it would increase to 10 per minute. (5+5+10) * 0.5 = 10
(The * means multiply, x)
If you remember your decimal fractions from school, these apply here. Basically:
1.00 = 100% - ie. the player's resource rate is not effected. In the above example, fuel would be collected at 5+5+10 = 20
0.75 = 75% - that resource is collected at 75%, fuel would be collected at (5+5+10) * 0.75 = 15
2 = 200%, the resource would be collected twice as fast, (5+5+10) * 2 = 40
Popcap is simply a set number, it will not be effected by how many strategic points the player controls, or any bonuses or upgrades.
Add this code a few lines below the "end" of your "OnGameSetup" function.
function test1()
Modify_PlayerResourceRate(player1, RT_Manpower, 2)
Modify_PlayerResourceRate(player1, RT_Fuel, 0.5)
Player_SetPopCapOverride(player1, 65)
end
***
Now, if you've already tried adding this function to your existing scar file, you'll have found that it not had an effect. The reason for this is that the function has not been "called" (ran), as you haven't told it to. (only special functions will autorun)
This brings us to the subject of how to link different functions together. There are two simple commands for doing this (there are others...)
Rule_AddOneShot
Rule_AddInterval
"OneShots" are just that - they will run your function once, at a time that you specify. "Intervals" will continuously run your function until told to stop.
For example, you might use a OneShot to setup the player's resource rates, as this might only need to be done once. Using an interval would cause the function to keep running, and would keep increasing or decreasing their resource rate to ridiculous levels.
Intervals are useful for say, continuously spawning waves of troops.
One thing to beware of is that you cannot run a function again while it is already running, this will cause an error.
Calling our Resource Rate Function
To make our function work, we need to tell it to run from a section of code that is already running, or going to run. As your "OnGameSetup" function automatically runs at the start of the game, this is a good place to start:
Add the following line to your "OnGameSetup" function
Rule_AddOneShot(test1, 10)
The first variable is the function we want to run, and the second variable is the time in seconds to wait before doing so. In this example, the game will wait 10 seconds before applying the resource rates, and you should notice it happening then as player1.
Two quick points about times. First of all, get used to working in seconds, for example 120 = 2 minutes, 600 = 10 minutes etc. Also, be aware that the times you put in are how long to wait for the function to be applied, from when the active function runs (the one the "OneShot" is being added from), this won't necessarily be the time since the start of the map! For example, if we added:
Rule_AddOneShot(test2, 60)
To our function "test1", "test2" would run one minute after "test1" ran, in this case, 1 minute and 10 seconds from the start of the map. Please don't actually add this line, as we don't have a "test2" it will cause the map to crash!
Once you've got this working, try adding further lines of code to your "test1" function. For example, you could try altering the resource rates, or copying and pasting the code and changing it to apply to other players. All you need to ensure is that the lines of code come before the "end".
Well Done! You're now able to heavily modify the way that your map will play - for example, you could heavily reduce the fuel income for all players, making the infantry phases longer, or increase it to quickly bring on the tanks...
Using Oninit to adjust player starting resources
OnInit is the second "special" function we will use. It runs just before your map begins, and is the only place where you can run certain commands. It also has a slightly different layout from other functions, but we'll get to that in a second...
function OnInit()
Player_SetResource(player1, RT_Manpower, 100)
Player_SetResource(player1, RT_Munition, 50)
Player_SetResource(player1, RT_Fuel, 50)
Player_SetResource(player1, RT_Action, 200)
end
Scar_AddInit(OnInit)
As you can see, the OnInit function requires an extra line of code after the "end" to make it start. This only applies to this special function. In the example above, we're using the "Player_SetResource" to alter a player's starting resources. There are 3 variables, the player it applies to, the resource to be altered, and the amount of that resource a player receives.
Hopefully you're getting familiar enough with scar code to understand what the first three lines will do. "RT_Action" is the number of experience points the player will start with (the ones you use to unlock off-map doctrine abilities) - 200 of them is equal to 3 commander points.
Now try adding the example code to your map, the traditional place is just below the "OnGameSetup" function.
Setting player doctrines
As well as giving your players free Commander Points, you can also pre-set a doctrine choice for them, and unlock specific abilities for them. However, doctrine choices will only apply if the player has selected the correct race for that doctrine, or has had it applied to them in the "race/army" choice we covered in part 2.
function sets()
Cmd_InstantUpgrade(player1, UPG.COMMANDER_TREE.ALLIES.AIRBORNE, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player1, UPG.ALLIES.GRENADE, ITEM_UNLOCKED)
end
The "InstantUpgrade" command applies to a variety of different areas, and can unlock global technology upgrades (for example, Grenades), doctrine powers, or even upgrades to an individual unit on the battlefield (this will be looked at in a later article).
In the example above, we unlock two upgrades for player1. The first line unlocks the "Airborne" doctrine, essentially bypassing the choice for the player. You can also unlock doctrine abilities for them at the same time (we'll cover this in the next example). The second line unlocks the "Grenade" upgrade from the barracks for the player, for free, even if they have not build one. You'll notice that the second variable, the "UPG." part, has a slightly different layout in the two lines - this is because the first line is unlocking a doctrine ability, and the second one a technology upgrade.
function sets()
Cmd_InstantUpgrade(player1, UPG.COMMANDER_TREE.ALLIES.AIRBORNE, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player1, UPG.COMMANDER_TREE.ALLIES.AIRBORNE_00, ITEM_UNLOCKED) --Paratroopers
Cmd_InstantUpgrade(player1, UPG.ALLIES.GRENADE, ITEM_UNLOCKED)
end
In this second example, we not only unlock the grenades, and the airborne doctrine, we also unlock the "Paratroopers" upgrade so that the player can immediately begin calling them in. You'll also have noticed that for the first time, we've used a "--" in the line so that we can add a label to our code. The computer will ignore anything after the -- on the line, so we can leave ourselves a reminder that this upgrade unlocks paratroopers, as this isn't immediately obvious when looking at the code itself.
Now, add the following line to your "OnGameSetup" function so that our new settings will be applied ingame:
Rule_AddOneShot(sets, 1)
Ok...so we know how to unlock the Airborne doctrine, and Paratroopers...just like in the campaign, but what about all the other doctrines and abilities in the game?
Well, this is a good time to have our first look at the relic code library. Within the zip file you can download in section 2 of this tutorial, you'll find a file called "luaconsts". Basically this is relic's list of all the units, buildings and abilities within the game, and how to refer to them using scar. Open the file using notepad, and go to the "Edit" Menu, then "Find", and type in "COMMANDER_TREE", then press "Find Next". This will automatically skip you down to the section that deals with unlocking doctrine choices and abilities.
Now, try altering the above code to open a different doctrine tree and ability. For example:
Cmd_InstantUpgrade(player3, UPG.COMMANDER_TREE.AXIS.DEFENSE, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player3, UPG.COMMANDER_TREE.AXIS.DEFENSE_12, ITEM_UNLOCKED) --Rocket Barrage
This would instantly unlock the Rocket Barrage ability for player3. You'll see that most of the "UPG." variable stays the same, but the final two parts have been altered. This is to direct the computer to the "Axis" abilities, and the "Defensive" doctrine. Now try applying doctrines to the other two army types.
As you can see, these commands give you an enormous amount of influence on how a game will play out - you can give players specific roles, and access to abilities that might be essential for playing or balancing your map. Balance is an important factor to consider when applying a lot of these changes - massively changing resource income, or giving one player access to abilities like the King Tiger early on can be completely game changing.
Also bear in mind that there are different restrictions on single and multiplayer games here. In a singleplayer game, you can give a player access to doctrine abilities that are not within the doctrine you've selected for them - for example you could give an airborne player Pershings as well. In multiplayer games, only powers from within a single doctrine can be unlocked.
Restricting Units, Technology and Buildings
As well as granting players upgrades, we can also deny them choices. It's important to consider carefully before doing this, as locking down too many different areas can make it difficult and frustrating for a player. Generally I'd say there are three cases when you might want to do this:
1) For map balance - when a specific unit or ability will make it far too easy to win. For example, in a convoy map I've made, 17 pounders and tank traps make it far too easy to stop the convoys. However, beware that you don't leave a player with no options for dealing with particular units!
2) For a "mini-mod" - for example, you may want to make your map infantry only, and you can do this by locking down all non-infantry units or buildings.
3) For co-op play - you may want to force the players to work together, and play particular roles. For example, you may want one player to use only airborne troops, so you lock any other units and buildings for them. It's important here to not completely straight-jacket a player, and to carefully think through the roles so they compliment each other.
Ok, on to the code:
Add these lines to your "sets" function:
Player_SetEntityProductionAvailability(player2, EBP.CW.ANTITANK_NEST, ITEM_LOCKED) -- 17 pounder
Player_SetSquadProductionAvailability(player2, SBP.CW.ARMOUR_HQ, ITEM_REMOVED) -- British Armor truck
Player_SetAbilityAvailability(player2, ABILITY.CW.HQ_REINFORCE, ITEM_REMOVED) -- HQ reinforcement
As you can see, we've used 3 different commands here to lock down the structures, units and upgrades respectively that a player could have used. As you'll also notice, we've used two slightly different 3rd variables here, "ITEM_LOCKED" and "ITEM_REMOVED". These serve two slightly different functions - locked items still appear in the menu, but are greyed out - however, they can be unlocked "normally" by the game, so for example if we locked the Armour_HQ instead of removing it, the player would unlock them when he builds a Captain. We could then unlock the 17 pounders later in the game, using the same line in a different function, but with "ITEM_UNLOCKED" instead. "ITEM_REMOVED" will make a unit or ability completely disappear from the User Interface (UI) and in the previous example, would not make Armour trucks available when the Captain is built.
Now try experimenting with the code, looking up the sections in "EBP" (for structures), "SBP" (for units), and "ABILITIES" for abilities in the Luaconsts file.
Phew that's quite a lot in one go - take some time to play around with the various functions here and get used to them. This leads us to our final section for today...
Debugging - ie. fixing your code!
You'll no doubt find at some point that when you load your map with the scar code, it will either freeze on starting, or give you a fatal scar error when a function is applied. This is because there's a mistake in your code somewhere - code is fussy, and needs to be perfect!
To explain a little more, computers are by their very nature, precise. They are incredibly quick at reading and following sets of instructions, but they have no common sense, or understanding of what they're actually doing. This means that your code must be free of typos, and bad "syntax" (computer grammar), or it will fail.
When this happens, you can press ctrl shift and ~ on your keyboard when in the game to access the console - this will describe to you what went wrong. Use the page up / page down keys to scroll, look for the section marked "FATAL SCAR ERROR" and the message next to it. This may or may not make sense to you, but it should at least give you a hint as to which section of your code to check. Most importantly, it will give you a "line number", which tells you which line to look at in your code - using mod studio or a coding program will allow you to find this line quickly.
The most likely errors are missing "ends", incorrect function names (for example you have have called your function "sets", but in your "Oneshot" referred to it as "set"), or made a typo in one of your commands or variables. For example, you have referred to SBP.CW.ARMOUR_HQ as SBP.ALLIES.ARMOUR_HQ or SBP.CW.ARMOR_HQ by mistake - the computer won't be able to find this and will freeze the code.
One big advantage of coding over map making is that you can fix your problems without having to exit the game. Just press ALT and TAB on your keyboard to minimise the game, and you can work on your code, save it, and tab back into the game to try it out. To do this, simply restart the map using the menu, or type "restart" into the console, and press enter.
Debugging can be a real headache, especially as your code file gets bigger and more complex. Try to regularly test your map when you add new code, and don't be afraid of changing the "OneShot" rules to apply much more quickly than you actually intend when playing the map for real. I'd also recommend copying and pasting code when possible, as this is quicker and is less likely to lead to a typo.
Ok that's all for today, please post any feedback from how you've got on, and anything in particular you would like to know how to do. Next time we'll have a look at spawning troops...
Cozmo
21st Jan 09, 11:22 AM
Sando, Only use things like Rule_AddOneShot etc, if you want to have a pause between when it is called and when it is executed... other wise just do it like this
test1()
that way if you want to call the function again later in the code you don't need to remove the previous rule.
(oh and Rule_* commands don't allow arguments)
sirpsychoj
22nd Jan 09, 3:00 AM
Great Work again Sando, never new about fixing my ERRORS whilst ingame, I always checked and fixed the error then repacked the files/map then restarted COH to only move on to the next error, tedious and frustrating, so thanks for your input. Feedback always helps someone and in this instance is no different, I was also thinking if the interest grows in this area, I would be willing to make little test maps to show the effects of the scar and could be uploaded as a file to watch from some sort of media player(rather than creating more confusion getting people to install demo maps) we could have it so it even shows script on the map pointing out whats going on and about to happen through a LocString, obviously we would only do this for the slightly more involved scar so pages and pages explaining it could be eliminated, so dont hesistate to ask for any input or help you may need in this area or any area, so good luck, thnx again, and help is here if its needed.
Mannerheim
22nd Jan 09, 3:11 AM
for debugging you can also reload the script without restarting the map, this is what i do with all my maps:
function OnInit()
if Misc_IsCommandLineOptionSet("dev") then
Scar_DebugConsoleExecute("bind([[ALT+1]], [[Scar_DoString('XDebug1()')]])")
Scar_DebugConsoleExecute("bind([[ALT+9]], [[setsimrate(10)]])")
Scar_DebugConsoleExecute("bind([[ALT+0]], [[setsimrate(100)]])")
end
end
Scar_AddInit(OnInit)
function XMaptest_Misc1()
Util_ReloadScript()
g_CheckAnnihilate = false
end
and alt-1 reloads the script, if the code stopped on error you can unpause the game after reloading
Cozmo
22nd Jan 09, 8:39 AM
Great Work again Sando, never new about fixing my ERRORS whilst ingame, I always checked and fixed the error then repacked the files/map then restarted COH to only move on to the next error, tedious and frustrating, so thanks for your input. Feedback always helps someone and in this instance is no different, I was also thinking if the interest grows in this area, I would be willing to make little test maps to show the effects of the scar and could be uploaded as a file to watch from some sort of media player(rather than creating more confusion getting people to install demo maps) we could have it so it even shows script on the map pointing out whats going on and about to happen through a LocString, obviously we would only do this for the slightly more involved scar so pages and pages explaining it could be eliminated, so dont hesistate to ask for any input or help you may need in this area or any area, so good luck, thnx again, and help is here if its needed.
With scripting, once you understand the basic principles of the language you can play around and advance pretty fast...
use the lua wiki (http://lua-users.org/wiki/TutorialDirectory) and search for the things you want to learn about, like lua tables, or lua loops etc.
sirpsychoj
22nd Jan 09, 11:03 AM
Cheers for that cozmoisme, much appreciated, and yes you can advance rapidly once you understand it more, but on the other hand, sometimes people, including myself, need ideas or we're not up to certain levels to maybe turn script we've made into a more simpler format. An example could be along the lines of repeated or unnecessary functions when it could have been put into a table(which is what i'm learning at present) to simplify it. And sometimes that can only come from forums like this from people like yourself willing to help others for free, thats why I feel seperating scar would greatly benefit this community and forum. Not trying to hijack your thread Sando, I'm just thinking if we can put up enough reasonable scar scripts that people would enjoy, all in one space for the time being, the great fella's who work for Admin :) and the greater community gets behind it :help: , they may consider it.
So here is an example of a script that would benefit others, but at the same time, if it could be simplified in a way that I still dont understand yet because I've yet to come across it, it would greatly benefit me and the others also.
I've made this script where if you capture a Control Tower at an Airport(load units in it and get the upgrade) a plane will spawn at end of runway(unfortunately no landing animations in COH) follow a path as if landing, slow down at certain point, engine/props cut revs, drops of units, continues along path, ups the revs/props, turns around then takes off and fly's away, at present i have it set to a AddIntervalEx/ so in other words a certain amount of times as not to overload the map with spawned units. But I'm sure a more experienced person maybe able to put this all in one function with alot less fuss( I'm hoping)
Compatibility: COH/OF., version 2.301
Ref: As above
import("ScarUtil.scar")
-- Called immediately on startup, this just sets out some parameters for the mission
function OnGameSetup()
-- set up the players
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
Rule_AddInterval(axis_control_tower1, 5)
end
function OnInit()
Scar_AddInit(OnInit)
----------------------- AXIS PLANE -----------------------
function axis_control_tower1()
if EGroup_HasUpgrade(eg_airport_control_tower, UPG.ELITE.CONVERT_AMBIENT_BUILDING, false) == true then
HintMouseover_Remove(LOCSTRINGS.CAPTURE_TOWER, mkr_capture_airport, 15, true)
Rule_AddIntervalEx(axis_plane1, 100, 5)
Rule_RemoveMe()
elseif EGroup_HasUpgrade(eg_airport_control_tower, UPG.ELITE.CONVERT_AMBIENT_BUILDING, false) == false then
end
end
function axis_plane1()
sg_plane1 = SGroup_CreateIfNotFound("sg_plane1")
Util_CreateSquadsAtMarkerFacing(player3, sg_plane1, SBP.ELITE.HENSCHEL_TAKEOFF, mkr_plane1, mkr_plane1a, 1)
Squad_SetAnimatorState(SGroup_GetSpawnedSquadAt(sg_plane1, 1), "nis_propeller", "on")
Modify_UnitSpeed(sg_plane1, 1.5)
Cmd_SquadPath(sg_plane1, "plane1", true, false, false, 0)
SGroup_SetInvulnerable(sg_plane1, true)
SGroup_EnableAttention(sg_plane1, false)
Rule_AddInterval(plane1a, 1)
Rule_AddInterval(axis_plane_troop_spawn, 5)
end
function axis_plane_troop_spawn()
if Prox_AreSquadsNearMarker(sg_plane1, mkr_plane1c, false, 10) and EGroup_IsCapturedByPlayer(eg_control_tower, player1, ANY) == true then
sg_1 = SGroup_CreateIfNotFound("sg_1")
Util_CreateSquadsAtMarkerFacing(player1, sg_1, SBP.ELITE.ASSAULTGRENADIER, mkr_player1_entrance, mkr_plane_troopspawn, 1)
UI_CreateMinimapBlip(sg_1, 10, BT_CombatPing)
Rule_RemoveMe()
end
end
function plane1a()
if Prox_AreSquadsNearMarker(sg_plane1, mkr_plane1a, true, 5) == true then
Squad_SetAnimatorState(SGroup_GetSpawnedSquadAt(sg_plane1, 1), "nis_propeller", "off")
Squad_SetAnimatorState(SGroup_GetSpawnedSquadAt(sg_plane1, 1), "taxi", "on")
Modify_UnitSpeed(sg_plane1, 0.10)
Rule_AddInterval(plane1b, 1)
Rule_RemoveMe()
end
end
function plane1b()
if Prox_AreSquadsNearMarker(sg_plane1, mkr_plane1b, true, 5) == true then
Squad_SetAnimatorState(SGroup_GetSpawnedSquadAt(sg_plane1, 1), "taxi", "off")
Squad_SetAnimatorState(SGroup_GetSpawnedSquadAt(sg_plane1, 1), "nis_propeller", "on")
Modify_UnitSpeed(sg_plane1, 1)
Rule_AddInterval(plane1c, 1)
Rule_RemoveMe()
end
end
function plane1c()
if Prox_AreSquadsNearMarker(sg_plane1, mkr_plane1d, true, 5) == true then
Squad_SetAnimatorState(SGroup_GetSpawnedSquadAt(sg_plane1, 1), "taxi", "on")
Squad_SetAnimatorState(SGroup_GetSpawnedSquadAt(sg_plane1, 1), "takeoff", "on")
Rule_AddInterval(remove_plane1, 5)
Rule_RemoveMe()
end
end
function remove_plane1()
SGroup_DestroyAllSquads(sg_plane1)
Rule_RemoveMe()
end
To those who are interested in this script, and may not understand it all, be Aware, that without other procedures first in setting it up on a map, this will crash. I just dont want to put it all up and feel like I've hijacked Sando's thread with his great work, so if he approves I can Edit it in cleanly or, Sando, please say if you prefer me remove it all and start a new thread all together, no offence will be taken, thnx
Cozmo
22nd Jan 09, 12:07 PM
man with out spacing that code is hard to read :P I'm gotta use notepad++ to divide out the functions ;).
sirpsychoj
22nd Jan 09, 12:09 PM
Soz, it was the way it came out when i copied and pasted, will redo with the slider so it stays in format, then re edit delete this post
Edit: Well its better but a few still have moved spaces but are still on there lines, ask on any info you may need on setting this up, as I have certain AI on my map Locked that these planes belong too or they'll behave how they want, the rest of setting it up is quiet simple, its more important where the markers are and that the plane flies out of bounds before it dissapears(set with a matching timer, otherwise you get a loop of same plane taking off) and making sure original rule does not overlap( meaning, if you start getting the next planes before the one before has left, it will cause an error). Which is a part that someone else maybe able to help so it doesnt do next rule unless first has left, anyway I can at some point today take a W/B snapshot of the airport setup, it will give you a thorough understanding of the setup,I'll do it so it shows the path, the markers, and the best outlay for the airport so the plane can come and leave, and the spawn markers for the plane and reinforcement squads
Edit: Here's a pic for you of my layout, the plane enters from right of screen, follows the path, slows within markers, spawns squad near marker(middle entrance,near craters) then continues on to end of path then takes off and flies back the same way it came. Im also thinking to play it safe so no interference from other units, painting tile so units cant go in area and make sure units spawn outside of it, or i can see an unintentional scar error occuring. Also the control tower in question is left/middle screen, has been made into _egroup and marker near it shows a mouse hint message. I have it in my map so enemy capture it and upgrade it to get there air units plus other air abilities related for the airfield, if anyone needs this code your welcome too it also. Im showing the axis version when they capture it as i cant seem to find an allies plane that has nis functions that i need at present, maybe others can help here too so planes match factions or we can at least have a allies fighter doing same. And one thing I nearly forgot, is the squads that spawn also follow a path in that script, its just I forgot to highlight it in W/Builder picture, but it leads from the marker I mentioned downwards towards the enemy. I also use this same priciple to add an atmosphere to the maps, by having men/units patrol areas, lights turning on and off, rotating towards an area if triggered, alarms and search patrols, overall creating activity so it resembles an active area owned by the enemy which you need to take control of through a mission objective, but I'm sure even my scripts can be collabarated into better more organised and more powerful scripts and hence the need for better forum publicity on scar and those who can help.
Cozmo
22nd Jan 09, 2:13 PM
Ok here is what I made, haven't tested it because I don't have the map... it will probably fail horribly until it is tested and debugged.
http://cozmo.pastebin.com/f50184853
sirpsychoj
22nd Jan 09, 2:24 PM
Wow....thats impressive, I will have to test it, but even still, it shows I have a long way to go and how complex things look to the mind when one still doesnt understand all capabilities of scar, my little bit of code looks overwhelming when put in its proper context to say the least
Cozmo
22nd Jan 09, 2:31 PM
Pm me any scar errors... (there will be some ;), nothing ever works first time).
Finaldeath
22nd Jan 09, 5:41 PM
Okay, moving to the tutorial forum.
lilmat1
23rd Jan 09, 12:35 AM
Here is my little bit...
This spawns a Higgins boats at a marker, which is actually a modified barracks with the blueprint of the Higgins boat.
And to have it face the right way, I placed a marker(facing1) on the right of each of the boat spawn(barracks1) markers.
function init1()
barracks1_BP = BP_GetEntityBlueprint("ebps/races/allies/buildings/barracks1.lua")
barracks1 = EGroup_CreateIfNotFound("barracks1")
EGroup_Clear(barracks1)
local entity = Entity_CreateENV(barracks1_BP, Util_GetPosition(mkr_boat1), Util_GetPosition(facing1))
Entity_SetPlayerOwner(entity, player1)
EGroup_Single(barracks1, entity)
sirpsychoj
23rd Jan 09, 9:56 AM
Nice lilmat1, I realise the Higgins is actually a modified relic object, but out of curiosity, can blueprint be changed on objects in scar format as easily as in mods, mods I know how to, scar I just cant seem to find anything I could use in a script, so if anyone knows how to achieve this, any chance of some input on a script. Also I'm sure I've seen someone mention about building normal buildings/dwellings (once again easily done in mods without matching animation) but I'm sure ive heard someone say they can build an object in scar, and by that I mean a unit with whatever script it needs to be able to build it and then more to the point that you can place it anywhere on map, so if this is also achievable can anyone help with suggestions, that would greatly benefit this tunnel network script I'm about to upload, because only restrictions on it at present is once again the building itself(egroup), it needs to be placed on map in W/Builder, and now come to think of it I'm presuming it would need to drop a marker? Is this possible and how? Once again, great work guys, keep it coming.
Here's a simple tunnel script you can use on your maps if you choose to implement it in a way that its not too unrealistic, by that i mean a building at each end of map and they go into tunnel and pop out other end in so many seconds in too unrealistic, I mainly use these for objectives, like sneaking into an area through an unlocked door as eg., and limiting it so your whole army cant pass through it. Very easy to setup,
(1) find a simple small looking building that could be used as an undercover tunnel entrance, place these on your map where you wish(then obviously detail them with bushes shrubs etc. so looks more the part) then place a marker with a specific name of your choose and alter my script with your new matching names. This is a simplified version and is only activated by the marker, when they warp to new position, you can make it so if units go in building(egroup) they can warp also, but i found most small buildings dont allow much over 3 units in a squad, and tunnels arent the size of houses, so it becomes more a personal choice of what you prefer.
Ver: COH/OF 2.301
Ref: Tunnel Network
Rule_AddInterval(tunnel_1, 3)
function tunnel_1()
if Prox_AreSquadsNearMarker(sg_axisrecon7, mkr_tunnel1_entrance, false, 10) then
Sound_Play2D(SOUNDS.AXIS_CONTROL_BUILDING)
warp_to_tunnel(4)
end
end
function warp_to_tunnel()
SGroup_WarpToMarker(sg_axisrecon7, mkr_tunnel1_end)
SGroup_WarpToPos(sg_axisrecon7, Marker_GetPosition(mkr_tunnel1_end))
Sound_Play2D(SOUNDS.AXIS_MOVING_OUT_BUILDING)
end
Be Aware to change marker names and your sgroups you want this to work on, with your own unique names matching your existing script.
Now if you want it so your men can get back home, you will need to make matching buildings and markers and set up like this. Also change the interval time to suit how long in your own preference it will take from entrance to end.
Rule_AddInterval(tunnel_1, 3)
Rule_AddInterval(tunnel_2, 3)
function tunnel_1()
if Prox_AreSquadsNearMarker(sg_axisrecon7, mkr_tunnel1_entrance, false, 10) then
Sound_Play2D(SOUNDS.AXIS_CONTROL_BUILDING)
warp_to_tunnel(4)
end
end
function warp_to_tunnel()
SGroup_WarpToMarker(sg_axisrecon7, mkr_tunnel1_end)
SGroup_WarpToPos(sg_axisrecon7, Marker_GetPosition(mkr_tunnel1_end))
Sound_Play2D(SOUNDS.AXIS_MOVING_OUT_BUILDING)
end
function tunnel_2()
if Prox_AreSquadsNearMarker(sg_axisrecon7, mkr_tunnel2_entrance, false, 8) then
warp_to_tunnel2(4)
end
end
function warp_to_tunnel2()
SGroup_WarpToMarker(sg_axisrecon7, mkr_tunnel2_end)
SGroup_WarpToPos(sg_axisrecon7, Marker_GetPosition(mkr_tunnel2_end))
Sound_Play2D(SOUNDS.AXIS_MOVING_OUT_BUILDING)
end
lilmat1
24th Jan 09, 3:00 AM
Thanks for that sirpsychoj. I certainly do not know if it can be done through scar. Some of the differences I have noticed with other peoples scar, mainly Mannerheim's and mine is that most things spawned, weather being units or vehicles buildings, or even abilities. Is that most are standard units, using the way relic does it.
So the way i spawn items is different. Only way I seem to be able to understand it. But also because the items I spawn are modified.
Unless I keep the same name of the object and then I have to do it differently.
So sirpsychoi, unless there is some blueprint area in the scardocs, you may as well do it in modstudio.
As for the second bit, there is some building markers and then using script to make the engineers build, may work.
Of course I don't know how to do that.
I hope I understood that correctly.
Sando
24th Jan 09, 5:05 AM
Excellent stuff guys, it's great to see some scar discussion and useful code being posted. Will hopefully have the next section posted this w/e - just need to paste the examples in.
SirPsychoj - a demo map with the code would be really useful - I had thought it would be useful as people would have a working example to play about with - if u get the chance would be great.
sirpsychoj
24th Jan 09, 9:55 AM
Thnx lilmat1, now that you mentioned those build markers, one would think thats what there for, so i'll look into it. Ok, great idea Sando, I'll post one up ASAP, I'll also upload my version of a build script as well, where i spawn engineers and they make sweet fortifications, then people will get the jist and be able to alter to there own build setups, then the pro's can look at my script and hopefully put it into a nice simplified setup. As much as I appreciated cozmoisme helping with that script he did above converting mine....it scared the hell out of me, :eek: seemed to be alot more complex and more work, but at the same time it definately opened my eyes and gave me a better understanding of how and what you can achieve, so I am grateful for that :agree:
Sando
26th Jan 09, 9:48 AM
If you've reached this section and have got the previous code working with your map, you're already making excellent progress in mastering scar.
Spawning troops can completely change the way your map plays, offering a big advantage to a player receiving the additional troops. Spawned troops are free, and you can also give them additional equipment, veterancy and modifiers (more on this later).
You should be very careful spawning troops that you don't unbalance the game - sheer weight of numbers, or even a few advanced units early in the battle can be game changers.
The "time" element of RTS's is vital, and when coding extra troops you need to keep in the back of your mind the impact they'll have. Imagine a King Tiger arriving 5 minutes into a game - this would be completely different to a unit of Riflemen arriving 30 minutes into the game.
Depending mostly on the amount of fuel and the number of resource points on a map, games will play out in roughly the same way, but at a different pace. Maps with low fuel will generally take longer to reach the more advanced stages, and player style can also have an impact here.
Most games evolve along these lines:
1) Start. Players begin capturing territory and building their bases.
2) Additional basic units are built and players may begin skirmishing.
3) Players tech up and begin to gain access to better kinds of troops. Generally better infantry, then light vehicles, anti-tank units, then tanks and artillery. Players will also begin accessing doctrine abilities.
4) Players fight the battle to a conclusion using the full range of troops and abilities.
Obviously strategies such as rushes, or fast techs may mean that the game does not reach the later stages.
Bear in mind that extra or advanced units tend to have more effect earlier in the game than later on, defeating a King Tiger 5 mins into the game would be almost impossible, while defeating one after 30 minutes is achievable.
Ok, time to look at some code...
Spawning a Unit
Remember back in the 1st section of this tutorial we talked about markers in World Builder? Now is the time to add one to your map - units cannot be spawned until you've added a "basic marker" to your map.
In World Builder, add a basic marker called "testmarker" to your map - usually map edges are a good place for these, as it looks more realistic when the unit appears.
Try to place it in a sensible location, such a road that goes into the OOB area. Also, take into account where you are placing it relative to the player bases as this can make a big impact - enemy reinforcements arriving in their base are almost the same as troops being built, while troops arriving behind your lines are more like an offensive, flanking force.
sg_support1 = SGroup_CreateIfNotFound("sg_support1")
Util_CreateSquads(player3, sg_support1, SBP.AXIS.VOLKSGRENADIER, testmarker, nil, 1)
This is the basic code for making a unit appear, we'll break it up to explain it.
The first line starting "SGroup_CreateIfNotFound" makes a "container" for the unit, and allow us to refer to it in future code. You can call a squad almost anything you like, but short, descriptive names with a number on the end work best.
The second line containing "Util_CreateSquads" is our actual command. It has 6 variables in this case. The first tells the computer which player the squad will belong to. The second, which "SGroup" (container) it belongs in. The 3rd is the type of unit to be spawned (this links up with the luaconsts file we looked at earlier). The 4th is the marker where the squad will be spawned, the 5th we can ignore for now, and the 6th is the number of squads to spawn - in this case 1 unit of 5 volksgrenadiers.
You can also spawn more than one type of unit within an SGroup (Squad Group or SBP Group), for example:
sg_support1 = SGroup_CreateIfNotFound("sg_support1")
Util_CreateSquads(player3, sg_support1, SBP.AXIS.VOLKSGRENADIER, testmarker, nil, 1)
Util_CreateSquads(player3, sg_support1, SBP.AXIS.GRENADIER, testmarker, nil, 1)
This code would spawn a unit of Grenadiers as well.
There are lots of ways of quickly spawning lots of troops, and randomising the types of troops spawned, but these will either be covered later on, or in a separate article.
Now, how to add the spawning troops to your working scar file - you have added that already marker, right?
First of all we add the new function, below the "end" of an existing one.
function testspawn()
sg_support1 = SGroup_CreateIfNotFound("sg_support1")
Util_CreateSquads(player3, sg_support1, SBP.AXIS.VOLKSGRENADIER, testmarker, nil, 1)
Util_CreateSquads(player3, sg_support1, SBP.AXIS.GRENADIER, testmarker, nil, 1)
end
We also need to "call" this function so that it runs. Add the following line to your "OnGameSetup" function:
Rule_AddOneShot(testspawn, 20)
Tada!? In this case, after 20 seconds player 3 will receive 2 free units wherever you have put the marker on your map. The assigned player or AI will automatically have control over them.
Spawning waves of Units
Now is a good time to try out the "Rule_AddInterval" command. If you remember, this tells the computer to repeat every number of seconds specified.
Go to your "OnGameSetup" function, and change the "Rule_AddOneShot(testspawn, 20)" line to read:
Rule_AddInterval(testspawn, 20)
If you try this ingame, the player will now receive those 2 free units every 20 seconds!
As you can imagine, even in this small example, this is the equivilent of that player receiving 270 + 300 manpower every 20 seconds, or 570 x 3 = an extra 1710 manpower per minute! So, the alternatives are to either make the rule repeat very slowly (say every 5 or 10 minutes), or to stop the rule from running after a certain period of time.
Removing an Interval Rule
You can remove a rule at any time, but it must already be running (ie. at a time interval) - "OneShots" cannot be removed in this way.
To remove our endless waves of troops, we'll remove our interval with another function:
function stopspawns()
Rule_Remove(testspawn)
end
This function will instantly stop the interval from repeating, so the key here is to time when we want the interval rule to stop. In this case, we'll do it by adding the following to our "OnGameSetup" function.
Rule_AddOneShot(stopspawns, 61)
This will remove the interval after 61 seconds, so the units will spawn 3 waves (20 x 3 = 60), and then stop. We could alter this number by increasing or decreasing the time until the stopspawns functions runs. For example, changing the time to anywhere between 41 and 59 will make it run twice, changing it to any number between 81 and 99 would make it run four times.
Experiment with this for yourself.
Spawning Different Types of Troops
To counter those Axis infantry, we'll need to deploy some allied jeeps, add the following to your code:
function testspawn1()
sg_support2 = SGroup_CreateIfNotFound("sg_support2")
Util_CreateSquads(player1, sg_support2, SBP.ALLIES.JEEP, testmarker, nil, 3)
end
And of course, to your "OnGameSetup":
Rule_AddOneShot(testspawn1, 25)
Notice that we've given these units a different sgroup, to not conflict with the axis units.
This will spawn 3 allied jeeps in the same place, a few seconds later. Any unit in the game can be referred to here simply by looking up it's name (SBP type) in the luaconsts file.
Once you've tried this, you'll notice that it's pretty silly having these units arriving in the same place as the axis infantry. Add another basic marker to your map in WB called "testmarker2". The change the above code example so that the jeeps spawn at "testmarker2" instead of "testmarker".
Giving your troops upgrades and veterancy
Not only can you pick which units to spawn, you can also equip them with specialised weaponry (eg. bazookas, mp40s etc) or veterancy. Bear in mind that veterancy works in the same way in scar as it does for the ingame races. Ie. US troops get veterancy on an individual unit basis, Wehrmarkt get a global upgrade for all their units of that type.
Here are some examples: (remember, you'll need to call these as part of a function to make them work, and they will only work if the unit/sgroup already exists)
Cmd_Upgrade(sg_support1, UPG.AXIS.GREN_MG42, 1, true)
This will give both squads an MG42. The number near the end of the line is how many of the weapons to give to each squad.
To balance this out, we'll give the allied squads extra veterancy:
SGroup_IncreaseVeterancyRank(sg_support2, 1, true)
Those jeeps will now gain level 1 veterancy...the middle variable is the level given to the troops. (In this case, "1"). This code works for US troops, but the other armies use different veterancy systems.
You can find a complete list of veterancy and upgrades in the luaconsts file.
Applying modifiers to your troops
Modifiers are useful and interesting, as you never consciously alter them when ingame. For example, when troops acquire veterancy this is often a set of modifiers,
e.g. Wehrmarkt veterancy gives bonuses to unit hit points and health regeneration rates.
The full list of possible modifiers is very long, and can be found in the "modifiers" file in the scar archive library.
Here's some examples to get you started:
Supercharged Pershing - the problem with heavy tanks is that they're soooo sloooow. Some bright spark at Allied Engineering wants to fit a normal Pershing with nitro's, and the results are...interesting...
Replace your testspawn1 function with the following instead:
function testspawn1()
sg_support2 = SGroup_CreateIfNotFound("sg_support2")
Util_CreateSquads(player1, sg_support2, SBP.ALLIES.PERSHING, testmarker, nil, 1)
Modify_UnitSpeed(sg_support2, 10)
end
When you launch the game, you'll notice that the Pershing's top speed has been increased by 10x - it can go really fast in a straight line. Notice that it still slows right down when turning - this is because we have only modified one aspect of the tank's stats.
Also, if you later called on another Pershing using the doctrine ability, it would not be supercharged as this modifier is only applied to the SGroup, not any unit built. Also, you can only change unitspeed on vehicles.
Reduced vulnerability
Adamantium Armour - although Pershings are tough, they still can't usually take on a King Tiger head to head...however, with our experimental new armour...maybe they can?
Replace your previous testspawn1 function with the following instead:
function testspawn1()
sg_support2 = SGroup_CreateIfNotFound("sg_supertank")
Util_CreateSquads(player1, sg_supertank, SBP.ALLIES.PERSHING, testmarker, nil, 1)
Modify_Vulnerability(sg_supertank, 0.5)
end
The Pershing is now 50% tougher and will take less damage in any firefight, and it is still relatively weaker at the back and sides. Reduced vulnerability works on any unit.
Please bear in mind that modifiers can be very potent, and I'd recommend using a light touch (i.e. small modifiers) or the results can appear very unrealistic to the player. 30% Maximum change is a good rule of thumb (0.7 to 1.3).
Modifiers are best used on special objective troops (eg. a tank the player has to destroy to complete a mission), to toughen/weaken troops for a particular kind of game (eg. attack/defend) or to create "Hero" units for the player to use.
More on SGroups
The keen mappers amongst you will have already noticed that in WB it is possible to make "Squad" and "Entity" groups from the "Groups" Menu. These groups link into scar like markers. SGroups (Squad Groups) can be used to name units, or groups of units - and then refer to them in code. This is essentially the same as the command "sg_support1 = SGroup_CreateIfNotFound("sg_support1")" only the unit already exists in WB and does not need to be spawned by code.
Moving your Units
Ok now that we can spawn units, you'll probably think at some point that you want some control over what the units do when they arrive. Units assigned to a player are controlled by that player, so while orders will be followed by spawning units, the player can overide them at any time.
This leaves you with 2 scenarios - giving units to a player, and giving them to the AI. Assigning units to human players will give them control over those units, and there's no way round this (Ok, there is, but it's tricky and the last time I checked only worked for single player maps - it crashes in multiplayer due to the distributed AI).
Giving units to an "active" AI player will mean that any orders you assign will quickly be replaced. However, we can get round this by disabling the "strategic" AI on a computer player.
We do this using the following command: (afaik, this should be in a separate function run very early in the map, not within a special function)
AI_Enable(player3, false)
Disabling the AI in this way has the following effects:
1) The effected AI player will not build any units, or move any troops, or generally do anything.
2) AI units will fight and seek cover as normal if any enemy unit is in range. (The "squad" AI still functions as normal)
3) Any scripted orders will be followed to the letter. Units will not retreat or use any special abilities unless told to.
This also gives us a method to control "allied" troops on the same side as a human player. We add another player to the map, and disabled the AI on it.
When and if to use "active" or "inactive" (disabled) AI players on your map is still a subject of some contention amongst coders. To begin with, most coders simply give units to an active AI player and let them use them - it's easier.
On the other hand, disabling all AI players and scripting orders for them gives you total control over how the AI will play, and map balance...very useful.
However, a fully scripted inactive AI player will only operate within the confines of the code - so how good your script is will make a massive difference to the playing experience. Unless you're an expert coder, this can lead to a lack of variety in how the map plays out over many games.
Personally, I take a middle route of using a combination of active and inactive AI to try and get the best of both worlds. However, there are many different opinions on this, and you'll want to make up your own mind, or even vary your approach dependent on your map's needs.
First of all, we need to add some movement markers in WB, personally I use cyan ones, but you can use any colour you like. Add 3 markers wherever you like on the map, called "move1", "move2" and "move3".
Ok, now on to some actual control commands, add this function, and call it from the testspawn1 function:
function movetank()
Cmd_Move(sg_supertank, Util_GetPosition(move1), true)
end
You'll notice that the move command needs to be assigned to a particular sgroup - and will only effect this group. The unit will simply move from it's current location, to the marker specified, as if you'd right clicked to move them there. In this case, as we've used a move command, the unit will attempt to fire it's weapon(s) on any enemy units that come within range (if the unit can fire while moving) but continue relentlessly to it's destination.
How about if we want to stop and attack any enemy units encountered, before moving on to the destination? Change your movetank function to the following:
function movetank()
Cmd_AttackMove(sg_supertank, Util_GetPosition(move1), true)
end
Both of these commands have their drawbacks - units on a "move" command will recklessly charge towards their destination, even if this means moving directly towards an MG Nest or anti-tank gun. On the other hand, units using "attackmove" will stop any fight any unit or building they encounter, even if they will likely be annihilated in the process. Also note, you don't need to use the full "Util_GetPosition(move1)" command, just "move1" will work.
Generally, I'd recommend using attackmove commands, as this seems to make more sense ingame for most units. Watching a mortar team charge an MG Nest is kinda silly. However, move commands are very useful when you want units to be more likely to reach their destination. (e.g. a good fire position, a strong attack that pushes through enemy lines, or an important objective).
Simple Waypoints
Before we start on this, all we're covering here is the simplest possible way of using waypoints. There are much better ways, but they rely on understanding "loops" (sections of code that repeat themselves) and "tables" (like an excel sheet where one row of commands is picked at random). We'll look at these in a later article.
For now, we can simply queue up a set of commands for the spawned units to follow, change your movetank function to:
function movetank()
Cmd_Move(sg_supertank, Util_GetPosition(move1), true)
Cmd_Move(sg_supertank, Util_GetPosition(move2), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move3), true)
end
Notice how we've used more lines of code, and how we've also changed the last variable to "True". This is because we want to queue up a series of orders, just like holding down shift when issuing commands ingame.
We can use even this simple code to achieve a variety of different results. For example, we could set the spawned units on a simple patrol:
function movetank()
Cmd_AttackMove(sg_supertank, Util_GetPosition(move1), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move2), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move3), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move1), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move2), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move3), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move1), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move2), true)
Cmd_AttackMove(sg_supertank, Util_GetPosition(move3), true)
end
(Bear in mind, we could shorten this by using an Interval rule to keep telling the units to do this - however, we'd then need to remove the interval if the units are destroyed). We could also use a loop function to achieve the same result, but we'll come to that in another article.
We could set an attack route, instructing the units to swiftly follow a pre-set route which we think might challenge the opposition, Or we could send the unit to defend a particular area by moving it there.
Bear in mind that because we have the AI disabled, once the troops run out of orders, they will just stand there and do very little unless attacked. For this reason, it's usually best to set a route that will eventually involve attacking all enemy bases, so the unit is unlikely to stand idle.
You may have noticed that this final example is longer than the others. Change your supertank to an infantry unit to see the effect properly, e.g.
Util_CreateSquads(player1, sg_supertank, SBP.ALLIES.RIFLEMEN, testmarker, nil, 1)
Cmd_Move(sg_supertank, Util_GetPosition(move1), NO_QUEUE, NIL_DEST, NIL_FACE, NIL_OFFSET, NIL_DIST, 10)
In this case, we've used some "optional" variables. Basically, these are variables for the command that you don't have to set - but you can if you want to. In this case the additional variables control where the unit will face towards, except the last variable - the number. This number is the "cover radius" the unit will use, so for example, the riflemen will still move towards their destination, but will utilise cover that they encounter within a small radius around their route.
Ok that's all for today, hopefully you'll now be able to spawn troops, change their stats, and get them to move around the battlefield under your instructions.
Next time, we'll have a look at controlling off-map abilities, how to make the code more random, and the map more responsive to how the game is progressing.
lilmat1
26th Jan 09, 11:10 AM
Looking Fantastic!! Sando.
If I may just add a little bit.
Most of the Scar explained here, is for standard maps or mods. But not for when you want to spawn "Modified" units, buildings, abilities.
You can of course add what you want to these items and "NOT" change the names and it will work the same.
But If you are wanting to do anything with "modified/Renamed"
units and such, this is where it can get tricky.
This code will spawn a "Modified/Renamed" unit to the field.
This example is for a renamed engineering squad...
sg_allies2 = BP_GetSquadBlueprint("sbps/races/allies/soldiers/engineer_infantrya.lua")
allies_02 = SGroup_CreateIfNotFound("allies_02")
Util_CreateSquadsAtMarker(player2, allies_02, sg_allies2, alliesspawn8, 1)
As you can see in the first line...
BP_GetSquadBlueprint("sbps/races/allies/soldiers/engineer_infantrya.lua")
You have to put in the new blueprint of that unit because this new blueprint is not in the original files in luaconts file.
Hope that helps with those that wish to add "modified" items.
Hope I got that right, first time I have tried to explain it...maybe some of this is rubbing off...
Cheers...
Sando
29th Jan 09, 7:41 AM
Hehe nice work Mat - I like the idea of using the higgins boats as barracks, makes much sense, game wise.
sirpsychoj
31st Jan 09, 4:33 AM
Hey Sando, just a quick question. I noticed in the above thread somewhere you mentioned -dev mode, Im curious, I run mine through the launcher without -dev mode with no problems, I always thought that the benefit of scar was that it can be put into any map and played online without problems and without the need for -dev as long as others have the map with the code. Have I got this wrong? And secondly, I should have the map with the plane functions up tomorrow sometime, Ive had to transfer to another map as I would like mine not be released until its finished (which is soon) Keep up with your great work
No worries SPJ - usually I work on the code while still working on the map/marker side, hence work with sgb's and -dev mode, but there's no need to do that if your method works. One thing with scar is that everyone has their own ways of doing things - always interesting to see. Working on a new map too at the mo so might be a while for the next part...
lilmat1
4th Feb 09, 10:15 AM
I can add a little more code for you people...
I initally tried to get this going with the help of cozmoisme.
Never got the flyovers to work.
Well finally, I thought I would have another look.
Looked in the caen scar files and found what I needed.
I shall explain a bit about it.
So the first part adds the ability once, with 20 sec delay.
The markers are, mkr_plane1(starting) and mkr_flying1(ending)
So lets say you start in the south of the map, a beach.
To have the plane start where you are and fly north, you position the markers in the north of the map.
Now between these two markers are where the planes would strafe or bomb, if you keep the artillery actions.
But I decided not to have anything. I set the blueprint to a C-47. Removed all the actions, as I only wanted it for some added eye candy. So the C-47 does not reveil any territory.
Now the way I have done this means, you have no control over the area where the planes fly or where an artillery action(bombing) will go.
This is by no means the only way to do it.
I am keeping it simple for me, and thats because I am still a novice and this scar.
Rule_AddOneShot(flyover1, 20)
function flyover1()
Cmd_Ability(player1, ABILITY.SP.CAEN_RECON_RUN, mkr_plane1, Marker_GetDirection(mkr_flying1), true)
end
Now I did modify the ability, but never renamed it.
So I was able to call it the way it is done in luaconsts.
This was one ability that really annoyed me.
So if you can't seem to get an ability working because you changed the name, keep the original and modify the other files that link to it.
Hope this helps some out.
Now I am going to try to get my artillery to work.
Cheers.
comeradealexi
25th May 09, 7:05 AM
Hey - i've been editing my map using your tutorial but i have one little problem - it is an eight player map and here is the code i am using:
function OnGameSetup ()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
player5 = World_GetPlayerAt(5)
player6 = World_GetPlayerAt(6)
player7 = World_GetPlayerAt(7)
player8 = World_GetPlayerAt(8)
Rule_AddOneShot(test1, 1)
end
function test1 ()
Modify_PlayerResourceRate(player1, RT_Manpower, 6)
Modify_PlayerResourceRate(player1, RT_Fuel, 4)
Player_SetPopCapOverride(player1, 250)
Modify_PlayerResourceRate(player2, RT_Manpower, 6)
Modify_PlayerResourceRate(player2, RT_Fuel, 4)
Player_SetPopCapOverride(player2, 250)
Modify_PlayerResourceRate(player3, RT_Manpower, 6)
Modify_PlayerResourceRate(player3, RT_Fuel, 4)
Player_SetPopCapOverride(player3, 250)
Modify_PlayerResourceRate(player4, RT_Manpower, 6)
Modify_PlayerResourceRate(player4, RT_Fuel, 4)
Player_SetPopCapOverride(player4, 250)
Modify_PlayerResourceRate(player5, RT_Manpower, 6)
Modify_PlayerResourceRate(player5, RT_Fuel, 4)
Player_SetPopCapOverride(player5, 250)
Modify_PlayerResourceRate(player6, RT_Manpower, 6)
Modify_PlayerResourceRate(player6, RT_Fuel, 4)
Player_SetPopCapOverride(player6, 250)
Modify_PlayerResourceRate(player7, RT_Manpower, 6)
Modify_PlayerResourceRate(player7, RT_Fuel, 4)
Player_SetPopCapOverride(player7, 250)
Modify_PlayerResourceRate(player8, RT_Manpower, 6)
Modify_PlayerResourceRate(player8, RT_Fuel, 4)
Player_SetPopCapOverride(player8, 250)
end
it works fine with all eight players but when i run the map with any of the slots closed the map crashes - any way around this apart from editing the code before every game? :S
thanks,
sirpsychoj
25th May 09, 9:26 AM
Use something like this, so its universal with 1,2 or 8 players.
for i = 1, World_GetPlayerCount() do
player = World_GetPlayerAt(i)
-- give set pop cap
Player_SetResource(player, RT_Command, 3)Player_SetPopCapOverride(player, 200)
Modify_PlayerResourceRate(player, RT_Action, 2.8)
Modify_PlayerResourceRate(player, RT_Munition, 2.8)
Modify_PlayerResourceRate(player, RT_Fuel, 2.8)
Modify_PlayerResourceRate(player, RT_Manpower, 1.7)
Player_SetAbilityAvailability(player, ABILITY.ALLIES.GRENADE, ITEM_UNLOCKED)
Player_SetAbilityAvailability(player, ABILITY.ALLIES.STICKY_BOMB, ITEM_UNLOCKED)
Player_SetUpgradeAvailability(player, UPG.ALLIES.BAZOOKA, ITEM_UNLOCKED)
Modify_VehicleRepairRate(player, 1.5)
end
So your code should look something like this now
function OnGameSetup ()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
player5 = World_GetPlayerAt(5)
player6 = World_GetPlayerAt(6)
player7 = World_GetPlayerAt(7)
player8 = World_GetPlayerAt(8)
Rule_AddOneShot(test1, 1)
end
function OnInit()
function test1 ()
for i = 1, World_GetPlayerCount() do
player = World_GetPlayerAt(i)
Modify_PlayerResourceRate(player, RT_Manpower, 6)
Modify_PlayerResourceRate(player, RT_Fuel, 4)
Player_SetPopCapOverride(player, 250)
end
comeradealexi
25th May 09, 2:40 PM
Sweet thanks a bunch - going to test it now - i guess that sets it for all players not just a specified one -thanks!
UPDATE: Just tried the code you gave me and it crashes while the game is loading :S
sirpsychoj
25th May 09, 2:54 PM
Okay, can you show me the warnings log?
Edit: was it because it doesnt have
import("ScarUtil.scar") -------at the very top of Scar file
comeradealexi
25th May 09, 3:01 PM
22:57:38.65 MessageInternal::CreateChannel: Created channel 474d4343
22:57:38.65 GameObj::OnFatalScarError: [string "DATA:Scenarios\MP\BIGFUN_ID.scar"]:27: 'end' expected (to close 'function' at line 19) near '<eof>'
22:57:38.65 GAME -- SimulationController::Pause 0
FATAL SCAR ERROR!
-- FATAL EXIT --
gameobj.c/4422:!
--stack trace--
i assume this is the part that is important?
added the scar thing to the very top of the code and it still crashed here is what warning was this time: 23:02:24.80 GameObj::OnFatalScarError: [string "DATA:Scenarios\MP\BIGFUN_ID.scar"]:29: 'end' expected (to close 'function' at line 21) near '<eof>'
23:02:24.80 GAME -- SimulationController::Pause 0
FATAL SCAR ERROR!
-- FATAL EXIT --
gameobj.c/4422:!
--stack trace--
sirpsychoj
25th May 09, 3:07 PM
Ok, thats a typing error in the script, its telling you that you either need an 'end' or you have to many end's on line 19/21, run it through ModStudio syntax and change until it says its ok, or if you dont mind, upload your new scar file. I have a feeling its missing an 'end' at end of scar file.
Edit: I just noticed this is for the Map ID_Scar, did you modify the ID file?
comeradealexi
25th May 09, 3:11 PM
http://rapidshare.com/files/237210033/BIGFUN_ID.zip
i dont see an attachment thing on the forum part?
but here is the scar file zipped up
---- i've been doing all these changes on: BIGFUN_ID.scar - should it just be BIGFUN.scar ?:S
sirpsychoj
25th May 09, 3:21 PM
Ok, simple to fix, you copied the scar_id file to make a new scar file, thats fine, but you need to remove the _ID from it, it should just be your maps name, but i'll load it up in studio and dbl check for any errors, will reply asap.
Edit: yeah it just needs to be a scar file, not a ID_Scar file, the ID file is for placements that are put on maps, eg. markers/groups etc. if you make a map like this then it would have both scar files
comeradealexi
25th May 09, 3:29 PM
Wow - thanks a lot dude - gunna test it now with out the ID btw
Ah - well i just put all the code into the BIGFUN.scar file and compiled the map - it loaded okay but nothing was changed :S
its like its not running the script now i think?
sirpsychoj
25th May 09, 3:33 PM
Okay here you go, all sorted, copy this over your previous scar file, and make sure theres no _ID on end of it
import("ScarUtil.scar")
function OnGameSetup ()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
player5 = World_GetPlayerAt(5)
player6 = World_GetPlayerAt(6)
player7 = World_GetPlayerAt(7)
player8 = World_GetPlayerAt(8)
end
Rule_AddOneShot(test1, 1)
function OnInit()
end
function test1 ()
for i = 1, World_GetPlayerCount() do
player = World_GetPlayerAt(i)
Modify_PlayerResourceRate(player, RT_Manpower, 6)
Modify_PlayerResourceRate(player, RT_Fuel, 4)
Player_SetPopCapOverride(player, 250)
end
end
it was missing the 'end' on On_Game_Setup, let us know if its all okay now, as it shows no errors in syntax
comeradealexi
25th May 09, 3:38 PM
I added that to the file but still nothing happened - this file isnt having an effect on the game :S
i put the _ID back on and it crashed with this error:
23:34:46.99 GameObj::OnFatalScarError: Invalid parameter 1 (type expected=unknown, received=nil) in function TimeRule_AddOneShot
Lua RuleSystem.scar Ln 70 (Rule_AddOneShot)
main BIGFUN_ID.scar Ln 15 ((null))
23:34:46.99 GAME -- SimulationController::Pause 0
FATAL SCAR ERROR!
-- FATAL EXIT --
sirpsychoj
25th May 09, 3:42 PM
Okay, Im gonna load it into a map to test, wont be long
Edit: Just a thought while I pack the map, do you still have an BIGFUN_ID scar file as well as your new BIGFUN scar file?
comeradealexi
25th May 09, 4:17 PM
I didnt have both at the same time no - it crashes when i just have the _ID.scar and does nothing with just the .scar
basically i only had one file present at any time - never both - should i have had both? with the ID just blank?
sirpsychoj
25th May 09, 4:20 PM
Okay, just tested the file, it works fine, yes the problem is its now missing the ID scar file, see if you can save your map again to creates its own, then all should be fine. If not create a new one, it should work, so it will be named BIGFUN_ID and look like this
function OnInitID()
-- [[ Markers ]]
-- [[ Squad Groups ]]
-- [[ Entity Groups ]]
end
Edit: yes both files need to be used
comeradealexi
25th May 09, 4:28 PM
I got bigfun.scar with the code: import("ScarUtil.scar")
function OnGameSetup ()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
player5 = World_GetPlayerAt(5)
player6 = World_GetPlayerAt(6)
player7 = World_GetPlayerAt(7)
player8 = World_GetPlayerAt(8)
end
Rule_AddOneShot(test1, 1)
function OnInit()
end
function test1 ()
for i = 1, World_GetPlayerCount() do
player = World_GetPlayerAt(i)
Modify_PlayerResourceRate(player, RT_Manpower, 6)
Modify_PlayerResourceRate(player, RT_Fuel, 4)
Player_SetPopCapOverride(player, 250)
end
end
and i have bigfun_id.scar with the code function OnInitID()
-- [[ Markers ]]
-- [[ Squad Groups ]]
-- [[ Entity Groups ]]
end
i open my map with the new code and press Export Package but when i get into the game nothing changed still :S - are you sure the last code you told me to use is the right one for the bigfun.scar?
sirpsychoj
25th May 09, 4:32 PM
Ok, important question, what are you using to repack maps, worldbuilder or CorsixModStudio, and also, are you running it in normal COH/OF/TOV with maps in sga format in docs or are you using -dev shortcut sgb maps?
Edit: also did you make the ID or resave map?
comeradealexi
25th May 09, 4:38 PM
i am using world builder and i am running maps from documents without the -dev shortcut
i made the ID - will delete and resave map too (this made the ID file - but its exactly the same)
sirpsychoj
25th May 09, 4:43 PM
Ahh, okay, I had a feeling that was the cause, unfortunately worldbuilder doesnt repack all the files, its leaving your scar file(new one) out, you will need to d/l Corsix Mod Studio and repack it with that, then you should be playing in no time. Do you know how the folders need to be set out when repacking maps?
Edit: its downloadable from this forum
comeradealexi
25th May 09, 4:54 PM
I got Corsix's mod studio - i opened the SGA file which i packaged from Worldbuilder but i dont know where to go from there - do you have a link to a tutorial which shows me how to pack it in Corsix?
soz to ask so many q's u been a great help!
sirpsychoj
25th May 09, 5:03 PM
No problems, I'll add a link to this post
Edit: I may as well just type it.
(1) To start, make a new folder on desktop with your maps name(BIGFUN) inside of that make another new folder and name Scenarios, now make another new folder inside that and name it MP, then put all your map/scar related files inside this. So it should look like BIGFUN/Scenarios/MP/ and all files.
(2) Open Modstudio, you need to load any sga file from C: programfiles/THQ/CompanyofHeroes/DLC1 and open any of the sga's in there, this is only to be able to use ModStudio as a packer, dont mod or save these files, it doesnt matter what sga is used, it could be in another folder(but must be inside main COH folder) its just the way Studio works to be able to open Studio if you dont have a mod made, if youve made a mod, then you could load the module of that and it will work the same.
(3) Now Studio is open, click on Mod on top left toolbar for dropdown menu, now click on sga packer, Input_directory is now asking you where the file is to pack, browse to your desktop and highlight your map folder, in the 'browse to folder box' that comes up with your map name, recopy the name and click ok.
(4) Now in the second part SGA_Create its asking where you want this saved, highlight(browse) your desktop or documents, because you may not be able to resave to desktop with both being same name, now paste in the name you copied in the SGA to create file name and click save.
(5) Now click create on the SGA Packer box, it all should be done now and on your desktop or documents, or wherever you chose to save it
comeradealexi
26th May 09, 1:20 AM
Okay i done all you said but somehow it still crashed :S
what was the code you used when you were testing it because here is what i am using import("ScarUtil.scar")
function OnGameSetup ()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
player5 = World_GetPlayerAt(5)
player6 = World_GetPlayerAt(6)
player7 = World_GetPlayerAt(7)
player8 = World_GetPlayerAt(8)
end
Rule_AddOneShot(test1, 1)
function OnInit()
end
function test1 ()
for i = 1, World_GetPlayerCount() do
player = World_GetPlayerAt(i)
Modify_PlayerResourceRate(player, RT_Manpower, 6)
Modify_PlayerResourceRate(player, RT_Fuel, 4)
Player_SetPopCapOverride(player, 250)
end
end
sirpsychoj
26th May 09, 5:31 AM
Nah thats the wrong one, here it is
import("ScarUtil.scar")
import("WCUtil.scar")
-- Called immediately on startup, this just sets out some parameters for the mission
function OnGameSetup()
-- used to indicate we want annihilate to be checked
g_CheckAnnihilate = true
-- set up the players
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
player5 = World_GetPlayerAt(5)
player6 = World_GetPlayerAt(6)
player7 = World_GetPlayerAt(7)
player8 = World_GetPlayerAt(8)
Rule_AddOneShot(test1, 1)
end
function OnInit()
for i = 1, World_GetPlayerCount() do
player = World_GetPlayerAt(i)
Modify_PlayerResourceRate(player, RT_Manpower, 6)
Modify_PlayerResourceRate(player, RT_Fuel, 4)
Player_SetPopCapOverride(player, 250)
end
end
Scar_AddInit(OnInit)
function test1()
end
The part I added for you doesnt need a rule, it runs from game start, but I left your rule there for future things you want to add and the Scar_AddInit function to then activate your rules. This all works now, tested. Btw, the resources ingame are excessive :nyah:
comeradealexi
26th May 09, 9:34 AM
Wow thanks so much dude - works perfectly now. Thanks a lot for all your help.
btw if i want to increase munitions cap i added "Modify_PlayerResourceRate(player, RT_Munitions, 6)"
but that doesnt work ?
sirpsychoj
26th May 09, 1:45 PM
No problems, glad to help. The reason RT_Munition, 6 isnt working is because you've added a "s" to the end of it, drop the s and it will work, if you have any future questions or problems, dont hesitate to ask.
comeradealexi
26th May 09, 3:11 PM
lol when typing it i was thinking hmmm munitions??
it doesnt say fuels or manpowers but they dont make sense!
lol
thanks for all ur help man!
SsOullesS
17th Jun 09, 10:53 AM
Hi, I just started learning SCAR, but at the very beginning I hit the wall. I can`t implement any SCAR to my maps (not even the basic one) every time I start playing (right after loading) the game freezes and the last thing in console is:
GAME- Starting mission...
after I double click pause it starts again but no SCAR is executed !?
Did someone had any similar problem and is this perhaps connected to sgb/sga map files (I tried everything I could remember)?
I always worked with .sga till now (for OF), but haven`t done this in a while.
Here is the screenshot of the problem, upper picture is before pause and the second after. Thx
http://i562.photobucket.com/albums/ss64/SsOullesS/SCAR.jpg?t=1245259449
sirpsychoj
17th Jun 09, 7:25 PM
It sounds like its your code that youve setup thats causing conflict, any chance of showing it to better help your problem.
toiletguy
18th Jun 09, 4:37 AM
Now!! The big problem!! Take a look at code plz!!
import("ScarUtil.scar")
function OnGameSetup()
--Setting Player Position
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
--Setting Player Name
local player1name = Util_CreateLocString("8th Army Battalion")
local player2name = Util_CreateLocString("SS Kommando Gruppe")
Setup_SetPlayerName(player1, player1name)
Setup_SetPlayerName(player2, player2name)
--Setting Player Army
Setup_SetPlayerRace(World_GetPlayerAt(1), 1)
Setup_SetPlayerRace(World_GetPlayerAt(2), 2)
--Modify Resource Rate
Rule_AddOneShot(resource, 5)
Rule_AddInterval(reinforcement, 5)
end
function OnInit()
--Setting Player Resource
Player_SetResource(player1, RT_Manpower, 1000)
Player_SetResource(player1, RT_Munition, 500)
Player_SetResource(player1, RT_Fuel, 150)
Player_SetResource(player1, RT_Action, 0)
Player_SetResource(player2, RT_Manpower, 1000)
Player_SetResource(player2, RT_Munition, 500)
Player_SetResource(player2, RT_Fuel, 150)
Player_SetResource(player2, RT_Action, 0)
end
Scar_AddInit(OnInit)
function resource()
Modify_PlayerResourceRate(player1, RT_Manpower, 2)
Modify_PlayerResourceRate(player1, RT_Fuel, 1.5)
Modify_PlayerResourceRate(player2, RT_Manpower, 2)
Modify_PlayerResourceRate(player2, RT_Fuel, 1.5)
end
function reinforcement()
sg_support1 = SGroup_CreateIfNotFound("sg_support1")
Util_CreateSquads(player2, sg_support1, SBP.AXIS.VOLKSGRENADIER, rf_1, nil, 3)
Util_CreateSquads(player2, sg_support1, SBP.AXIS.GRENADIER, rf_1, nil, 1)
Util_CreateSquads(player2, sg_support1, SBP.AXIS.PANTHER, rf_1, nil, 1)
end
Help!! No reinforcement!!
Edit: One morething!! It say Cannot start OnGameSetup!!
SsOullesS
18th Jun 09, 6:26 AM
Sure, here is the code. It`s quite simple:
import ("ScarUtil.scar")
function OnGameSetup ()
player1 = World_GetPlayerAt (1)
player2 = World_GetPlayerAt (2)
local player1name = Util_CreateLocString ("150th Rifle Division")
local player2name = Util_CreateLocString ("27th Panzer Division")
Setup_SetPlayerName (player1, player1name)
Setup_SetPlayerName (player2, player2name)
Setup_SetPlayerRace (World_GetPlayerAt(1), 0)
Setup_SetPlayerRace (World_GetPlayerAt(2), 3)
end
It`s similar with toiletguy`s problem. Everything is fine - until the game starts, then it freezes and after you double click pause or menu it starts normally but something overrides the SCAR code and it doesn`t execute. I even try`ed the simplest code I could remember
import ("ScarUtil.scar")
function OnGameSetup()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
local player1name = Util_CreateLocString("150th Rifle Division")
local player2name = Util_CreateLocString("27th Panzer Division")
Setup_SetPlayerName(player1, player1name)
Setup_SetPlayerName(player2, player2name)
end
same thing.
toiletguy
18th Jun 09, 7:06 AM
So...?
lilmat1
18th Jun 09, 1:15 PM
I'll See if I can help...
This is how I do my code, it's mainly for modified units...
import("ScarUtil.scar")
function OnGameSetup()
-- this is called as the game sets up, not when it is initalised.
-- you cannot call functions from here since the game has not started yet.
g_CheckAnnihilate = true
-- Setup_Player already returns a player ID so you don't need the
-- World_GetPlayerAt bit.
player1 = Setup_Player(1, 18010003,"Allies",1)
player2 = Setup_Player(2, 18010003,"Allies",1)
player3 = Setup_Player(3, 18010002,"Axis",2)
player4 = Setup_Player(4, 18010002,"Axis",2)
end
function OnInit()
-- this is called when the game initalises, so you can call functions from it.
Rule_AddOneShot(init1, 0)
Rule_AddOneShot(flyover, 15)
Rule_AddInterval(flyover1, 325)
Rule_AddOneShot(demo1, 15)
Rule_AddOneShot(artillery1, 2)
end
Scar_AddInit(OnInit)
function init1()
--UI_BindingSetEnabled("company_commander", false )
--UI_ForceCommanderTreeChoice(player1, UPG.COMMANDER_TREE.ALLIES.INFANTRY)
Player_SetUpgradeAvailability(player1, UPG.COMMANDER_TREE.ALLIES.INFANTRY, ITEM_UNLOCKED)
Player_SetUpgradeAvailability(player1, UPG.COMMANDER_TREE.ALLIES.AIRBORNE, ITEM_LOCKED)
Player_SetUpgradeAvailability(player1, UPG.COMMANDER_TREE.ALLIES.ARMOR, ITEM_LOCKED)
Player_SetUpgradeAvailability(player2, UPG.COMMANDER_TREE.ALLIES.INFANTRY, ITEM_UNLOCKED)
Player_SetUpgradeAvailability(player2, UPG.COMMANDER_TREE.ALLIES.AIRBORNE, ITEM_LOCKED)
Player_SetUpgradeAvailability(player2, UPG.COMMANDER_TREE.ALLIES.ARMOR, ITEM_LOCKED)
Player_SetUpgradeAvailability(player3, UPG.COMMANDER_TREE.AXIS.DEFENSE, ITEM_UNLOCKED)
Player_SetUpgradeAvailability(player3, UPG.COMMANDER_TREE.AXIS.PROPAGANDA, ITEM_LOCKED)
Player_SetUpgradeAvailability(player3, UPG.COMMANDER_TREE.AXIS.BLITZKRIEG, ITEM_LOCKED)
Player_SetUpgradeAvailability(player4, UPG.COMMANDER_TREE.AXIS.DEFENSE, ITEM_UNLOCKED)
Player_SetUpgradeAvailability(player4, UPG.COMMANDER_TREE.AXIS.PROPAGANDA, ITEM_LOCKED)
Player_SetUpgradeAvailability(player4, UPG.COMMANDER_TREE.AXIS.BLITZKRIEG, ITEM_LOCKED)
Cmd_InstantUpgrade(player1, UPG.GRENADE, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player1, UPG.DEMOLITION, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player1, UPG.STICKY_BOMB, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player1, UPG.BAR, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player2, UPG.GRENADE, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player2, UPG.DEMOLITION, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player2, UPG.STICKY_BOMB, ITEM_UNLOCKED)
Cmd_InstantUpgrade(player2, UPG.BAR, ITEM_UNLOCKED)
--FOW_RevealMarker(mkr_beach, -1)
-----FOW_RevealArea( markerpos, markerprox, duration )-----
Util_PlayMusic("SOUND/Music/enterthesqarecombat", 0, 0)
--g_alarm_soundpath = "SpecialFX/alarm_02"
Player_SetPopCapOverride(player1, 110)
Player_SetPopCapOverride(player2, 110)
Player_SetPopCapOverride(player3, 130)
Player_SetPopCapOverride(player4, 130)
Modify_PlayerResourceRate(player1, RT_Manpower, 2.5)
Modify_PlayerResourceRate(player2, RT_Manpower, 2.5)
Modify_PlayerResourceRate(player1, RT_Munition, 1.7)
Modify_PlayerResourceRate(player2, RT_Munition, 1.7)
EGroup_SetInvulnerable(building1, true)
EGroup_SetInvulnerable(building2, true)
EGroup_SetInvulnerable(building3, true)
EGroup_SetInvulnerable(building4, true)
EGroup_SetInvulnerable(building5, true)
EGroup_SetInvulnerable(building6, true)
EGroup_SetInvulnerable(bunker1, true)
EGroup_SetInvulnerable(bunker2, true)
EGroup_SetInvulnerable(bunker3, true)
EGroup_SetInvulnerable(bunker4, true)
EGroup_SetInvulnerable(bunkerbig1, true)
EGroup_SetInvulnerable(bunkerbig2, true)
EGroup_SetInvulnerable(bunkerbig3, true)
EGroup_SetInvulnerable(bunkerbig4, true)
EGroup_SetInvulnerable(bunkerbig5, true)
EGroup_SetInvulnerable(bunkerbig6, true)
---Cmd_InstantEntityUpgrade(building3, UPG.CONVERT_AMBIENT_BUILDING, 1)
---Cmd_InstantEntityUpgrade(building4, UPG.CONVERT_AMBIENT_BUILDING, 1)
barracksboat_BP = BP_GetEntityBlueprint("ebps/environment/art_ambient/objects/vehicles/military/barracks_boat.lua")
barracksboat = EGroup_CreateIfNotFound("barracksboat")
EGroup_Clear(barracksboat)
local entity = Entity_CreateENV(barracksboat_BP, Util_GetPosition(mkr_boat1), Util_GetPosition(facing1))
Entity_SetPlayerOwner(entity, player1)
EGroup_Single(barracksboat, entity)
weaponsboat_BP = BP_GetEntityBlueprint("ebps/environment/art_ambient/objects/vehicles/military/support_weapons_boat.lua")
weaponsboat = EGroup_CreateIfNotFound("weaponsboat")
EGroup_Clear(weaponsboat)
local entity = Entity_CreateENV(weaponsboat_BP, Util_GetPosition(mkr_boat2), Util_GetPosition(facing2))
Entity_SetPlayerOwner(entity, player1)
EGroup_Single(weaponsboat, entity)
----player 2 boats----
barracksboat_BP = BP_GetEntityBlueprint("ebps/environment/art_ambient/objects/vehicles/military/barracks_boat.lua")
barracksboat = EGroup_CreateIfNotFound("barracksboat")
EGroup_Clear(barracksboat)
local entity = Entity_CreateENV(barracksboat_BP, Util_GetPosition(mkr_boat3), Util_GetPosition(facing3))
Entity_SetPlayerOwner(entity, player2)
EGroup_Single(barracksboat, entity)
weaponsboat_BP = BP_GetEntityBlueprint("ebps/environment/art_ambient/objects/vehicles/military/support_weapons_boat.lua")
weaponsboat = EGroup_CreateIfNotFound("weaponsboat")
EGroup_Clear(weaponsboat)
local entity = Entity_CreateENV(weaponsboat_BP, Util_GetPosition(mkr_boat4), Util_GetPosition(facing4))
Entity_SetPlayerOwner(entity, player2)
EGroup_Single(weaponsboat, entity)
-----axis bunkers-----
--bunker_BP = BP_GetEntityBlueprint("ebps/environment/art_ambient/objects/defenses/concrete/bunkerm01_02.lua")
--bunker = EGroup_CreateIfNotFound("bunker")
--EGroup_Clear(bunker)
--local entity = Entity_CreateENV(bunker_BP, Util_GetPosition(mkr_bunker1), Util_GetPosition(mkr_bunkerface1))
--Entity_SetPlayerOwner(entity, player1)
--EGroup_Single(bunker, entity)
-----allies 1-----
sg_allies2 = BP_GetSquadBlueprint("sbps/races/allies/soldiers/engineer_infantrya.lua")
allies_02 = SGroup_CreateIfNotFound("allies_02")
Util_CreateSquadsAtMarker(player1, allies_02, sg_allies2, alliesspawn1, 1)
sg_allies3 = BP_GetSquadBlueprint("sbps/races/allies/soldiers/battle_sim_ranger_team_bazooka.lua")
allies_03 = SGroup_CreateIfNotFound("allies_03")
Util_CreateSquadsAtMarker(player1, allies_03, sg_allies3, alliesspawn1, 1)
---- allies 2 ----
sg_allies2 = BP_GetSquadBlueprint("sbps/races/allies/soldiers/engineer_infantrya.lua")
allies_02 = SGroup_CreateIfNotFound("allies_02")
Util_CreateSquadsAtMarker(player2, allies_02, sg_allies2, alliesspawn10, 1)
sg_allies3 = BP_GetSquadBlueprint("sbps/races/allies/soldiers/battle_sim_ranger_team_bazooka.lua")
allies_03 = SGroup_CreateIfNotFound("allies_03")
Util_CreateSquadsAtMarker(player2, allies_03, sg_allies3, alliesspawn10, 1)
------axis troops player3-----
sg_bunkermg1 = BP_GetSquadBlueprint("sbps/races/axis/soldiers/heavy_machine_gun_autotarget.lua")
bunkermg_01 = SGroup_CreateIfNotFound("bunkermg_01")
Util_CreateSquadsAtMarker(player3, bunkermg_01, sg_bunkermg1, mkr_garrison1, 1)
Cmd_InstantGarrison(bunkermg_01, bunkerbig1)
Cmd_Attack(bunkermg_01, mkr_mg2,true, -1)
sg_axis2 = BP_GetSquadBlueprint("sbps/races/axis/soldiers/sniper.lua")
axis_02 = SGroup_CreateIfNotFound("axis_02")
Util_CreateSquadsAtMarker(player3, axis_02, sg_axis2, mkr_garrison1, 1)
Cmd_InstantGarrison(axis_02, bunkerbig5)
------axis troops player4----
sg_axis2 = BP_GetSquadBlueprint("sbps/races/axis/soldiers/sniper.lua")
axis_02 = SGroup_CreateIfNotFound("axis_02")
Util_CreateSquadsAtMarker(player4, axis_02, sg_axis2, mkr_garrison4, 1)
Cmd_InstantGarrison(axis_02, bunkerbig4)
---Cmd_Garrison(axis_02, bunker3)
sg_axis10 = BP_GetSquadBlueprint("sbps/races/axis/soldiers/officer_squada.lua")
axis_10 = SGroup_CreateIfNotFound("axis_10")
Util_CreateSquadsAtMarker(player4, axis_10, sg_axis10, mkr_garrison6, 1)
end
---fly overs---
function flyover()
Cmd_Ability(player1, ABILITY.SP.CAEN_RECON_RUN, mkr_plane1, Marker_GetDirection(mkr_plane1), true)
Cmd_Ability(player1, ABILITY.SP.CAEN_RECON_RUN, mkr_plane2, Marker_GetDirection(mkr_plane2), true)
Cmd_Ability(player1, ABILITY.SP.CAEN_RECON_RUN, mkr_plane3, Marker_GetDirection(mkr_plane3), true)
end
function flyover1()
Cmd_Ability(player1, ABILITY.SP.CAEN_RECON_RUN, mkr_plane1, Marker_GetDirection(mkr_plane1), true)
Cmd_Ability(player1, ABILITY.SP.CAEN_RECON_RUN, mkr_plane2, Marker_GetDirection(mkr_plane2), true)
Cmd_Ability(player1, ABILITY.SP.CAEN_RECON_RUN, mkr_plane3, Marker_GetDirection(mkr_plane3), true)
end
-----starting artillery-----
function demo1()
Cmd_Ability(player1, ABILITY.SP.SINGLE_CREEPING_MORTAR, Marker_GetPosition(mkr_demo1), nil, true)
end
function artillery1()
Cmd_Ability(player1, ABILITY.SP.SINGLE_HOWITZER, Marker_GetPosition(introarty1), nil, true)
end
---artillery through out game---
function mortar1()
Cmd_Ability(player1, ABILITY.SP.SINGLE_MORTAR, Marker_GetPosition(arty1), nil, true)
end
As with you code, it seems ok to me. But since you are trying to spawn 3 different types of units, try this...
function reinforcement()
sg_support1 = SGroup_CreateIfNotFound("sg_support1")
Util_CreateSquads(player2, sg_support1,
SBP.AXIS.VOLKSGRENADIER, rf_1, nil, 3)
sg_support2 = SGroup_CreateIfNotFound("sg_support2")
Util_CreateSquads(player2, sg_support2, SBP.AXIS.GRENADIER, rf_1, nil, 1)
sg_support3 = SGroup_CreateIfNotFound("sg_support3")
Util_CreateSquads(player2, sg_support3, SBP.AXIS.PANTHER, rf_1, nil, 1)
end
toiletguy
18th Jun 09, 6:08 PM
I know what is problem now. I remove Setup Player name and everything go fine.
How do u i know unit name like "SBP.AXIS.PANTHER"?
SsOullesS
25th Jun 09, 11:53 AM
Yeah, same thing. For some reason that command won`t work.
Everything else work`s excellent.
Anyway, our petition for separate section for SCAR remained unanswered by Admin, so how about making a Sticky Thread in Map`s Bunker for SCAR maps?
Just like "Map List", but exclusively for SCAR (map`s).
It would be better to have them all on one place, instead of chasing them around forums.
Kabizzle
2nd Jul 09, 11:01 AM
HI Guys im having a problem w/ my map scar...
if i choose annihilate and start the game, it starts up showing the victory points and icons etc...however, when ppl capture the points, the VP tickers dont go down...its as if the victory points are there but dont matter
additionally, it never seems to get past OnGameSetup()...
heres the code:
import("ScarUtil.scar")
function OnGameSetup()
-- -- define player variables used by various functions
-- g_CheckAnnihilate = true
player1 = Setup_Player(1, "Americans","Allies",1)
player2 = Setup_Player(2, "Americans","Allies",1)
player3 = Setup_Player(3, "Axis","Axis",2)
player4 = Setup_Player(4, "Axis","Axis",2)
end
function OnInit()
Rule_AddInterval(bombingRuns, 30)
-- --for starter units use markers 29-33
end
Scar_AddInit(OnInit)
function bombingRuns()
--use markers 5-28
plyr=World_GetPlayerCount()
if World_GetRand(0, 1) == 0 then
bomber = World_GetPlayerAt(World_GetRand(1, plyr))
mark=Marker_FromName("mkr_"..World_GetRand(5,28), "cyan_marker")
target = Util_GetPosition(mark)
target.x = target.x + World_GetRand(-50, 50)
target.z = target.z + World_GetRand(-50, 50)
direction = Marker_GetDirection(mark)
direction.x = direction.x + World_GetRand(-90, 90)
direction.z = direction.z + World_GetRand(-90, 90)
btype = World_GetRand(0,3)
if btype == 0 then
Cmd_Ability(bomber, BP_GetAbilityBlueprint("abilities/ally_air_strike_ability_rockets.lua"), target, direction, true)
elseif btype == 1 then
Cmd_Ability(bomber, BP_GetAbilityBlueprint("abilities/off_map_artillery_ability.lua"), target, direction, true)
elseif btype == 2 then
Cmd_Ability(bomber, BP_GetAbilityBlueprint("abilities/overwatch_barrage.lua"), target, direction, true)
elseif btype == 3 then
Cmd_Ability(bomber, BP_GetAbilityBlueprint(ABILITY.COMMANDER_TREE.ALLIES.STRAFE_MG), target, direction, true)
end
end
end
function reinforceRohan()
--use marker 4
end
function reinforceCorsairs()
--use marker 3
end
SsOullesS
25th Jul 09, 11:00 AM
I made a new thread in Map`s bunker, list for SCAR map`s only, so be free to post your work.
Here`s (http://forums.relicnews.com/showthread.php?p=3596525#post3596525) the link.
sadflux
20th Aug 09, 8:54 AM
Hi, I'm new
The tutorial is realy nice good work!
But I have the same problem, too. I can`t implement any SCAR to my maps (not even the basic one) every time I start playing (right after loading) the game freezes.
after I double click pause it starts again but no SCAR is executed !?
Have anybody the solution of this problem?
thx
Mobius
5th Sep 09, 3:49 PM
It doesn't seem to work, I tried to spawn stuff and it doesn't seem like its trying to read it period. :noway:
Now I must of did something cuz its freezing at the beginning of the game. But when I hit Pause it kicks back in but still nothing happens
here is what I have.
import("ScarUtil.scar")
function OnGameSetup()
player1 = World_GetPlayerAt(1)
player2 = World_GetPlayerAt(2)
player3 = World_GetPlayerAt(3)
player4 = World_GetPlayerAt(4)
local player1name = Util_CreateLocString("British X Corps")
local player2name = Util_CreateLocString("British 2 Commando")
local player3name = Util_CreateLocString("4th Wehrmarkt Army")
local player4name = Util_CreateLocString("15th Panzer Elite")
Setup_SetPlayerName(player1, player1name)
Setup_SetPlayerName(player2, player2name)
Setup_SetPlayerName(player3, player3name)
Setup_SetPlayerName(player4, player4name)
Rule_AddOneShot(test1, 1)
Rule_AddOneShot(testspawn, 1)
Rule_AddOneShot(moveman1, 1)
Rule_AddInterval(testspawn, 5)
end
function test1()
Modify_PlayerResourceRate(player1, RT_Manpower, 2)
Modify_PlayerResourceRate(player1, RT_Fuel, 0.5)
Player_SetPopCapOverride(player1, 200)
end
function testspawn()
sg_support1 = SGroup_CreateIfNotFound("sg_support1")
Util_CreateSquads(player3, sg_support1, SBP.AXIS.VOLKSGRENADIER, s_depoteast1, nil, 1)
Util_CreateSquads(player3, sg_support1, SBP.AXIS.GRENADIER, s_depoteast1, nil, 1)
end
function moveman1()
Cmd_Move(sg_supertank, Util_GetPosition(moveman1), true)
Cmd_Move(sg_supertank, Util_GetPosition(moveman1), true)
end
SuperWarDude
14th Sep 09, 9:36 PM
help! the download for the SCAR command library is gone! i really need it. can anyone bring it back? :puppy:
9-28-09 - It has been a long 14 days and still no answer. man i need those commands. The file is missing dude.
Hawkwind
28th Jan 10, 1:58 PM
Same here,
I got some idea's that I like to try to run through SCAR, but I need to see that Relic libary page. The link just brings you to a missing file page.
Please if there is a new link post it.
sirpsychoj
29th Jan 10, 7:36 AM
I'm assuming this is what you are after, all the function lists? http://www.europeinruins.com/ScarDoc/scar_doc.htm
Hawkwind
29th Jan 10, 12:33 PM
yes
thank you!
This appears to be it.
vBulletin v3.0.7, Copyright ©2000-2010, Jelsoft Enterprises Ltd.