Search This Blog

Sunday 5 May 2002

How to get Co-op to work with MoH:AA


This is for use with Medal of Honor: Allied Assault

What is Co-Op play?

This is where you and your friends combine forces to complete the missions within the game. You all compete against the computer.
The maps and levels have to be created or modified to be played co-op.

What needs to be done?

There is a convenient feature of the game, that allows any level to be played Co-Op, as long as both the server and the client run the same level, before the client attempts to connect to the server.
Use a few command line options to launch the map and run the server at the same time, then the client can use the console command 'connect' to join that game.

To simplify things, the shortcut is usually provided by any modified co-op level, and can easily be changed to work with other levels.

I have created some menus, to simplify the client side of things, see further on in this guide.

Although I have said any level can be played co-op, this is misleading, because the objectives and obstacles in some Single Player levels, do not function or can not be passed by more than one player! This is why most levels have to be modified to work. In addition, some levels are too easy, when a team try to complete them. For this reason I have created some scripts to help improve co-op levels. This guide does not cover those, just the basics.

Which version of MOH:AA will I need?

I have only been able to get Co-Op play to work properly, if I patch up to version 1.11 of the game. If you stick to an older version, you're on your own.
If you can't upgrade your game because it claims you have the wrong country version, there is a registry fix to correct the version number.

[HKEY_LOCAL_MACHINE\SOFTWARE\EA GAMES\Medal of Honor Allied Assault\1.1.12.200]

What files do I need to modify?

You need:
Maps\coop_yourlevel.bsp (the main compiled map file)
Maps\coop_yourlevel.scr (script file - this is the one you have to edit)
Maps\coop_yourlevel_precache.scr (this is a list of all the models and the script used in the game)
The game will create the following automatically, once created, it's worth putting them in your pk3 file:
Maps\coop_yourlevel.min
Maps\coop_yourlevel.pth

How do I get characters to fire back?

Include the modified .tik file:
models/human/new_generic_human.tik

How do I get the sound to work?

Make sure your map files start with 'coop'.
Include the ubersound files, which have been modified to include map files that start coop as well as the normal ones:
ubersound/uberdialog.scr
ubersound/ubersound.scr
These files are included in any of my modded levels, look for the lastest mod on my web site and download that. 'x_jcbmain###.pk3' contains the sound and human model fixes. The hash (#) will be the version number of that file.

Several mods will have modified these files, so if the sound does not work, remove any other mods. I have tried to get my version to work with as many mods as possible, but due to the way mods and the files in MOH:AA work, it is not possible for all mods to be compatible.

What do I need to change in the scr file?

1) Remove all the friendly troops.
Add the following line to the script file:
$friendly remove
or
$friendlybob remove
$fredflintstone remove
$friendly2 remove
They are the targetnames of the characters followed by the command 'remove'. If the friendly characters do not all have the targetname 'friendly' you will have to put one line in for each targetname.

2) Remove any model, object or door that gets in the way.
$object_targetname remove

3) Fix the guys who jump out of cabinets. (if present)
Search for any line in the script that looks like this:

exec global/cabinet.scr
Change the line to have 'remove' at the end.
exec global/cabinet.scr remove
I don't know why it works, but I found this tip in the big 5 map pack notes and was originaly found by Fatz, thanks.

4) Disable any code that does not work.
Each map will have different problems. Some maps have vehicles at the start of the level which may need disabling and removing others may have events that cause problems, for example the alarms in m6l2a get turned on by the guards but can't be turned off by the players. In this case remove the alarm code:

// exec global/alarmer.scr
The // is the comment marker, so if a line starts with // it will not be executed.
Other lines I've had to remove to get things to work:
// exec global/spotlight.scr
The following line is possibly used in other scripts, but generally I have found it can be removed with no noticable consequenses.

level.script = maps/mxly.scr
The following, and anything refering to the $player, will not work on the server, until the $player is alive. On the server it is not good enough that the player has spawned.
In the main code, the script lines will have been processed BEFORE the player is alive, so that code will not work! For simplicity, you can simply remove those lines, but if they add to the plot, you may want to spend the time re-writing them in some way!

Examples of ones that can be removed:

$player stufftext "tmstop"

5) Check lines with references to other file names.
In most cases you should LEAVE the map name as per the original level. The script that is called will only have entries for existing levels. You may want to edit the script that is called to work with your level name, although this is usually unnecessary.

exec global/loadout.scr maps/mxly.scr // this assigns player items for the level
The loadout script can be removed. In single player it adds appropriate weapons, but this is overridden by the multiplayer weapon selection when playing co-op.
Leaving it usually creates more errors than it saves, but I am undecided. If you want to leave it, use the following line in all the co-op scripts.
exec global/loadout.scr maps/m5l3.scr // CO-OP to reduce warning error messages
It should be the first line of the level script.
exec global/ambient.scr mxly // this adds suitable background sound

6) Remove or change the objectives.
This can be tricky, but the level will probably work without touching the objectives. If parts of the level are not playable in Co-Op, try just removing the objectives. If you are familiar with scripting, you can probably set up a suitable Co-Op objective for the level.

** That's it, you should now have a Co-Op level.

7) Fix the enemy skill level.
This can be labourous. Normal SP skill levels are ignored when running a Multiplayer server. Most SP levels set the accuracy of the enemy to 100% and then use the skill level to adjust it down for the SP games. This can make Co-Op levels difficult but still fun.

If you want to feel better about your skill, you can use the 'targetname' of each character and set the accuracy of each enemy:

$guard_by_the_gate.accuracy = 20
$patroller1_in_yard.accuracy = 15
$enemy.accuracy = 25

How do I find individual characters or objects in an existing map?

Use a hex editor on the .bsp file and search for 'targetname'. Look for lines of code similar to the following:
{
"balconyheight" "128"
"enemysharerange" "0"
"#fnum" "1"
"origin" "-5392.00 -2368.00 72.00"
"testanim" "idle"
"model" "human/1st-ranger_medic.tik"
"scale" "1.0"
"classname" "ai_allied_2nd-ranger_private"
"$targetname" "friendly"
"type_idle" "idle"
"type_attack" "turret"
"type_disguise" "salute"
"type_grenade" "grenade"
"gun" "none"
"maxdist" "328"
"angle" "0"
"leash" "900"
"sound_awareness" "100"
"noticescale" "100"
"fixedleash" "0"
"waittrigger" "0"
"accuracy" "20"
"ammo_grenade" "0"
"disguise_range" "256"
"disguise_period" "15"
"disguise_level" "1"
"gren_awareness" "10"
}

How do I reference an individual character in my script?

You can reference the characters by their Targetname. The targetname acts on all the characters with that targetname all at once.
"$targetname" "friendly" "$targetname" "guard1" "$targetname" "officer2"

For example, to remove all the characters with the targetname 'friendly' use:

$friendly remove
or to remove individual characters you could use:
level.guy = $guard1
level.guy remove
It might be possible to reference the characters by their friendly number, but I have never tried to get that to work...

"#fnum" "1"
"#fnum" "2"
It's probably just the array number, e.g.
$friendly[2] remove

How do I reference the players in my script?

This is tricky but possible, but requires the addition of some simple code. As each player spawns $player becomes an array with one member for each player. $player[1], $player[2] etc.
To find out the total number of players connected check the array size.

level.total_players = $player.size
In addition to that, to reduce the amount of work the server has to do, I keep track of the maximum number of clients, using:
level.maxplayers = int ( getcvar (sv_maxclients) )
You can use these in a loop similar to the following:
loopforgame:
  for(local.i = 1;local.i <= $player.size;local.i++)
    {
        if ($player[local.i] isTouching $item_targetname)
        {
 iprintlnbold "Do something here..."
        }
        waitframe //infinite loop protection
    } //end loop for players
  waitframe //infinite loop protection
goto loopforgame
end
For this to work, you will have to loop indefinetely which could slow the game down, so be sparing with this type of code and make sure you have the waitframe commands in the right places.

How do I display messages on the players screen?

iprintln "A message"
iprintln_noloc "A message"
iprintlnbold  "A message"
iprintlnbold_noloc "A message"
Using the _noloc (no localisation) avoids the 'Need Localisation' errors, see the next section.

Why do I get 'Need Localisation' errors in the console?

All text you use needs to be in the localization.txt file to stop these errors. The game looks for a substitution, between the English used and the language you want to display. It will not stop the text displaying, but is a bit messy, so you might want to always use the _noloc versions of the iprint command.

Where do I put my code?

I find that adding or removing objects and most setup code works, if it is after:
//------------------------------------------------------
level waitTill prespawn
//------------------------------------------------------
and before:
//------------------------------------------------------
level waitTill spawn
//------------------------------------------------------
If it is something that happens, rather than adding or removing objects, or it has to interact with the player, it should be after:
//------------------------------------------------------
level waitTill spawn
//------------------------------------------------------
Having said the above, I am actually still not sure if the 'level waitTill spawn' works at all in multiplayer games. I have taken to removing it from my Co-Op scripts.

How can I make the levels easier to start?

I have created menus for this purpose. I am on my second version. These add to the level script, and pop up a menu when the players run the level.
See any of my new levels, the code is right at the start. You can find these on my web site. The menus are included in 'x_jcbextras###.pk3' supplied with each of my Co-Op levels. Look for the latest version number instead of the hash (#).

Can I use DM Maps for Co-Op

Not really, I have tried and I can add lots of troops using scripts, BUT I can't get them to patrol or move about, so the gameplay is a little boring. They duck and shoot at you, but that's about the best I can get.
I have tried to add info_pathnode entities to move actors to and from but the maps always crash. I have had confirmation from other people that adding info_pathnode entities crashes maps, so at the moment I've given up with DM maps.

SP Maps

The Single Player maps have lots of useful scripting worth having a read through.

Are they any good for Co-Op Play?

The following are just a few notes I have made about each level:
A=Already Co-Op, N=Needs work, E=Easier conversion
N * m1l1 Start in moving truck
N * m1l2a training
N * m1l2b training factory cut wires bit dull
N * m1l3a Moving jeep
A * m1l3c Road to lighthouse

A * m2l1 snow meet grillo - the snow one in Norway
N * m2l2a Need to check papers
N * m2l2b inside sub (too small)
E * m2l2c Outside sub, alarms sounding (needs work, OK, but small)
E * m2l3 inside building but starts inside the air con (needs work but OK.)

A * m3l1a Omaha landing (already done by someone else)
A * m3l1b Omaha bunker (already done by someone else)
A * m3l2 Farm house, with a platoon
E * m3l3 Six barrelled (needs rocket laucher, may be worth a look)

E * m4l0 Road up to house
A * m4l1 before plane then road to tunnel under church
A * m4l2 Train depot, (avoided need to get on the truck)
E * m4l3 truck to tank park (small but OK)

A * m5l1a Snippertown (needs some more work.)
A * m5l1b Lead Tank crew (needs some more work.)
N * m5l2a Tank
N * m5l2b Tank
N * m5l3  Protect Tank at bridge (too small)

E * m6l1a Snow forest
E * m6l1b More snow
N * m6l1c Need papers to get to riffle Stg44
A * m6l2a Snow leading to town - communication blackout
A * m6l3a Starts in a train with marines (marines removed!)
N * m6l3b Fort. (Starts in a lift)
N * m6l3c Fort again. (Starts in a lift again)
N * m6l3d More in the Fort (worse, wearing Gas Mask)
N * m6l3e End game (very short)

Thanks

I'd like to thank the numerous people on Forums, Newsgroups and Web Pages who have provided useful information to help me write mods and prepare these notes. Most of you are unidentifiable or lost in the mists of re-posts and quotes. If you happen to see something that you think you originated, then you are probably correct, and many thanks.