MOH Design FAQ


Global

Q:How do the scripts tie into the levels?

A:The game automatically loads the script file that has the same name as the level. Loading m5l1a.bsp will load m5l1a.scr. Scripts can also load global scripts by exec'ing them (like exec global/weather.scr), which adds additional functionality that you wouldn't want to write into the level scripts. Most levels will load auto.scr at the beginning. Auto.scr automatically loads various scripts (which scripts are loaded can be seen by opening up auto.scr in notepad).

Q:How do you implement weather? (Rain, Snow…)

A:You need to create rain volumes (create a box inside of which you want the rain to fall, make it func_rain and give it the common/rain texture).

For rain, do:

exec global/weather.scr 
at the beginning of the level's script.

For snow, try this example thread from the snowy forest (mohdm5) that adds snow:
snow:
 wait 1  
 level.rain_speed = "32"
 level.rain_speed_vary = "16"
 level.rain_length = "2"
 level.rain_width = "1"
 level.rain_density = ".2"
 level.rain_slant = "250"
 level.rain_min_dist = "1800"
 file://level.rain_min_dist = "512"
 level.rain_numshaders = 12
 level.rain_shader = "textures/snow0"
end


Q:How is dialog triggered? If I want someone to say something to the player at a certain point, how do I set it up?

A:You can place trigger volumes in a level that the player walks through to set off (trigger_once with the key "setthread" and value of whatever thread in the script you want it to run). In the thread you could have any AI you wanted say a line. You could also have them turnto or lookat the $player first.

Most talking is done by waiting until the player is close to the friendly (for example doing a while loop seeing if the vector_length $player.origin - ai.origin) < 300), and then telling the ai to lookat the player, then doing a say command, and then a waittill saydone on the AI before it continues to do anything else.


Q:What's our max poly count? On screen? In a level?

A:Our plan for MOHAA: Spearhead was to stay between 12k and 16k total polygons in any given scene (at maximum LOD settings). The visible brush count in a level ranged from 6500 to 8000 or so. The maximum level total was determined by the maximum size of the bsp file, which we had at 10MB.


Q:How does the AI on your team work?

A:Open friendly.scr. There is a long section at the top of that script describing how to use it. There is also useful information at the top of AI.scr.


Q:For example, what in the script makes a group of guys follow you through a level? And how do they decide where to go? It seems that they have a separate path that they must stay near as they navigate through a given level, is this correct?

A:Yes. In MOHAA: Spearhead they follow paths (a series of linked info_pathnodes) that begin with a pathnode that has the targetname "friendlychain". This is clear on t1l3 and t2l1. You can turn these paths on and off in script whenever you like, to make friendlies stop progressing (evident in t1l3 and t2l1, again). Or, you can just set friendlies to friendtype 1 and they will follow the player where ever he goes.


Q:How do the exec global/friendly.scr::friendlythink and exec global/enable_ai.scr script commands affect the AI?

A:Friendlythink turns on the friendly's "friendly AI" that makes them follow the player in some way. You never want to do this more than once on a friendly. global/enable_ai.scr and global/disable_ai.scr enable and disable any AI's combat AI. If you disable it, they will not pay any attention to enemies. Use this with caution.


Q:How do I get friendly AI to branch away from the player and do his own thing? For example, you fight alongside the Captain for a while, then he gives you an order and goes off on his own. You meet up with him later, etc.

A:You would disable his friendly AI by setting his friendtype to -1 and then either wait for him to get out of combat (do a while (self.thinkstate != "idle") or while (self.thinkstate == "attack")), and then tell him to do explicit things like talk to the player or run somewhere, and he will do it.


Q:What are AI leashes used for?

A:They set the distance the AI is willing to move from wherever they are when combat begins. All AI wants to stay within the bounds of their leash.


Q:AI seems to be spawned immediately when a level loads. Is there a way to spawn guys when a trigger is fired instead? For example, what if I want a group of guys to be spawned upstairs and then run down the stairs, but not until the player walks in a certain doorway?

A:Yes. Create a trigger volume "enemyspawnertrigger" and link (select the trigger, THEN the AI and hit ctrl-K) it to AI (any number of AI. You may have to manually assign them targetnames to actually give them all the same targetname). The AI themselves can be linked to individual nodes (select the AI, THEN the node and hit ctrl-K). When the player hits the trigger, the AI will spawn and they will run to those nodes and then fight the player.


Q:Is there a set on-screen character limit?

A:No. The more you add, the slower the game gets. What do you think this is? A stinkin’ console game??


Q:How do you set up some Nazis firing an MG42?

A:The simplest way is to do it like the mg42 gunner in t1l2. Place an mg42, give it $targetname "mg42", and target it to an AI. The AI will use the gun. If you want a new AI to spawn and run to the gun when the gunner is killed, then target the gunner to another AI. That AI will be the spawn point for the new gunner when the current gunner dies.

This functionality uses turret.scr so you would have to "exec global/turret.scr" at the beginning of your script (or "exec global/auto.scr").


Q:How do I get the stopwatch to pop up in my mission?

A:The script line is “$player stopwatch x” (x=# of seconds)


Q:What about look at triggers?

A:The line of script is “if ($player cansee self x)” where x=the FOV. See training.scr for details.



Editor

Q:I need to minimize my editor every time I run the game. How do I get around this?

A:Enter in “r_fullscreen 0” at the console and restart the game. If you end up with the game in a small window, change your resolution in the game to match the resolution of your desktop. If you don’t know what this means, get a job washing cars.


Q:The entity window pops up every time I run the game. That sure is annoying. What should I do?

A:If you run the game in a window (see above), this will no longer happen.


Q:Any lighting tips? Is there a quicker way to see the results of lighting changes you make?

A:You can compile maps using -fast in mohlight to give you a rough approximation of the end result. Light is pretty slow, although surface lights and radiosity are especially slow. Use "-bounce 0" to get rid of radiosity.


Q:Is the caulk texture all you need to use to make sure a poly/brush won't draw? We've heard of a caulk shader as well, or is it the same thing?

A:Everything is a shader. Use "common/caulk" to make a surface not draw.


Q:Explain the difference between the AI window (push I) and the Entity window (push N) when dealing with AI. Why would you have to call the AI parameters window up vs. doing these things in the entity window?

A:The AI parameter window is like a shortcut. When you first create an AI, his parameters aren't available in the entity window. You have to call up the AI window to add them (otherwise they're just defaults).


Q:Efficient terrain building tips? Should we use patches liberally?

A:You're better off sticking with terrain. Patches where AI or the player will actually walk need to have invisible brush collision created for them because curves don't approximate good collision.

For terrain, keep any terrain that touches level geometry at low or medium tolerance (of LOD), but terrain that is not connected to curves or brushes can be fairly low LOD (high tolerance). Be sure to flag terrain that will never be seen as "delete" (ctrl-shift-LMB to select, then shift-F, check “delete”).


Q:We are experiencing bsp leaks from doors, lights and the like. Any tips on avoiding/eradicating these?

A:In the level editor go to "file" and click "pointfile". If you are compiling in the same directory you are loading maps from, then you will see a red line in the level going from outside the level, through the leak, to inside.


Q:How do I create collapsing or exploding geometry?

A:1) Create the pre-destruction geometry, make it a script object in the entity window. Give it and all of the following relating pieces a #set number so you can have multiple instances of collapsing geometry in a given level.

2) Give the geometry the $targetname exploder.

3) Make the destroyed version of the geometry, make it a script object in the entity window.

4) Give the destroyed geometry the $targetname explodersmashed.

5) Create a trigger_multiple with the $targetname explodertrigger. Check the damage box in the entity window. This trigger should encompass however much of the geometry you want to react to bullets. If you want a wall to collapse when it is shot, surround the whole wall with this trigger.

6) For debris that flies away from the geometry when it explodes, create another script object with the $targetname exploderchunk. Place a script origin and target it (ctrl-k) at the chunk. The chunk will fly towards the origin when the explosion occurs.

7) For explosion effects, place a script model and give it a $targetname of exploderfire.

8) For collapsing geometry, you can place add some variables to an exploderchunk - #xrot xx/#yrot xx/#zrot xx . This will make the geometry will rotate along the specified axis as it moves towards it’s assigned script origin.



Regarding path nodes:

Q:What attributes can be assigned to them?

A:$Targetname if you want to reference them specifically in script. In some cases angle is relevant too. There is an AI document in the docs (AI tips.doc) that has a lot of specific stuff about path nodes and how AI relates to them.


Q:Why don't you have to change their direction in the entity window (they seem to work fine pointing in any direction)

A:They indicate where AI can go, they don't tell AI which way to point when they're going there (except in special circumstances like with cover nodes and corner nodes).


Q:How far apart should they be?

A:No more than 320 units max.



Random Editor tips

- Ctrl-Alt-E Shows everything in the world an entity is linked to.

- Ctrl-Alt-MMB when pointing at the floor and having an entity selected will place that entity at ground level. Real useful when placing AI guys & pathnodes.

- Ctrl-Alt-Shift-Click duplicates and links. Very useful when building a path network.

- Ctrl-D hides all detail brushes, very useful.

- Don’t use the “sniper” checkbox on pathnodes. It’s broken.

- When setting up an alarm guy, set his alarm node (in the AI parameters window) to the same name as his target node. See m4l3 for reference.

- If you put $ in front of a string or # in front of a number in the entity window, you can reference them in script. Examples would be $targetname or #set.

- Setting an AI to #playerseek 0 in script will cause him not to seek out the player (he’ll act like a guard).

- level.totalbaddies is used as a checker for how many AI are alive in your level. So you could say if level.totalbaddies < 3 then send reinforcements, etc.

- You can check if the player is inside of a trigger area by using istouching in script. If istouching $targetboxname etc…

- You can change a guy to ai_actor in the entity window if you would like to change the color of his box in the editor. This is useful for distinguishing between spawned vs. placed AI, for example. Or you could make the main level boss one color and his helpers the default, etc.

- #fnum – set this number in an AI’s entity window if you want adjust his specific behavior. IE, you have a squad of guys with your, one of which you want to be a medic. If you give him an #fnum, you can call out his friend number in script and make him a medic.

- Crates and walls that you want AI to crouch behind and fire over should be around 48 units tall. Place nodes pointing TOWARDS the wall right next to the wall, and in the entity window check the CRATE checkbox.

- If you want to trigger something only once, place a trigger_multiple down and change it to trigger_once in the entity window. Simply placing a trigger_once may cause problems.

- println is the script command for printing debug messages on the screen.

- Indoor and Outdoor ambient sounds are placed by putting triggers in doorways that are labeled ($targetname) either interior or exterior and are given a #set of 1-3.

-tmstart is used to play one shot sounds


Brushes

- Skip brush can be used as a reference point when using the editor, since in the game it has no collision and doesn’t draw.

- Weapon clip blocks bullets.

- Area brush – creates vis for func_doors. Put these brushes INSIDE of your doors to block vis beyond them (since func_doors will not block vis into a room).

- Caulk Sky is a brush used for foggy levels… use this if your fog will obscure the skybox, negating the need to draw it.

- Clip brush clips just the player. Useful for keeping him out of areas.

- Clipall clips EVERYTHING. Bullets, player, AI, etc.

- Hint splits up vis.

- Material specific clips (carpet, grass, etc.) are for hit effects & sounds.

- Actor clip is for clipping AI, if you don’t want them to wander somewhere.

- Obscure brushes are to add realism to AI combat – they will confuse them as far as targeting goes. Good for placing in bushes and what not if you don’t want the AI to accurately target the player while he’s hiding in them.


Random console commands

- debug 1 at console brings up a bunch of neat debug info.

- Entering in g_scriptcheck 2 at the console will crash out the game if there are script errors

- ai_showroutes 1 in console shows AI pathing stuff

- ai_showpath1 / 2 can be used in conjunction with tele xyz to check for broken paths.

- timescale x speeds up the game by x amount.

- ai_delete 1 kills all AI in a level.