Lucas' Simpsons Hit & Run Map Builder > Tutorials > Map Building Tutorials > The Basics > Making a Basic Map

Making a Basic Map

This tutorial will guide you through the bare minimum steps to make a basic custom map work in-game.

By the end of this tutorial, you should have a small map that is just a square piece of ground with a couple locators.

NOTE: Missions will not yet work in this map and it will not have a custom HUD map. This tutorial is just the bare minimum required to go ingame, you will also need to follow the Adding Roads tutorial after this one for missions to work.

Prerequisites

You will need a PC copy of The Simpsons: Hit & Run as well as the following tools to accomplish the steps in this tutorial:

Part 1: The Mod

To actually play our map in-game, we'll first need a basic mod to start with. We've gone ahead and created a basic mod for these purposes that you can download here.

This mod contains the following:

  • A basic Meta.ini that requires the Custom Files and Custom Interior Support hacks.
    • Custom Files is used to let the mod provide custom files of course.
    • Custom Interior Support is used to redefine and remove the Evergreen Terrace interiors from this custom map as they are not applicable in this map.
  • A set of Level scripts to load everything needed for our map.
    • These also load a provided dummy door stars file to remove door stars as they are also not applicable in this map.
  • A couple dummy missions with no objectives that will let us jump into our map by creating a new game from the main menu or by selecting Level 1 Mission 1.
  • A folder named "_Assets" that you'll work out of.

You will need to extract the "Tutorial Map" mod folder inside the ZIP linked above into any of the Mod Launcher's default mods folders or any custom ones you have defined in the Launcher's Settings to be able to use the mod.

Once you have the mod in place, you're ready to start making a brand new map.

Part 2: The SketchUp File

Step 1: Setting up SketchUp

SketchUp's interface is very customizable so depending on your chosen layout you may not have certain important panels in view. We'd like to make a couple recommendations for the purposes of these tutorials and creating maps in general.

Since the Map Builder relies heavily on a hierarchy of groups with special names and tags within their names to work we'd first like to recommend that you keep the Outliner easily accessible. If you don't currently have a tray with the Outliner in it, you can go to Window > New Tray... to create one containing it. You may also want the Entity Info panel in the same tray as it will make editing attributes of the currently selected object easier.

With large models that have many thousands of groups, you may experience slowdown having the Outliner open so it may be good to get used to minimizing it by clicking the arrow near its header when you're not using it. It would also be very beneficial to learn and understand how to make use of Layers for larger map projects.

You will also want the Materials and Components panels accessible. You can technically put these in the same tray though if you have a good amount of screen real estate or multiple screens, it might be better to make another new tray containing just them.

Also note that all new models start with a Component named "Chris". He's not really relevant to what you're going to be doing and you can leave him there or delete him, it's up to you.

Step 2: Save the model

You haven't done anything yet but it's good to start by saving your model. For the purposes of these tutorials, you should save it as "Map.skp" in the "_Assets" folder of the mod you extracted in Part 1.

Step 3: Terrain

You'll want to start by making some basic "terrain" in your SketchUp model, for the purposes of this tutorial, you should use a flat rectangle (though you could really use whatever you want).

You should make this rectangle about 20 meters by 20 meters so there's a good amount of space to walk around.

flat plane

Step 4: Setting up the groups

Now that you have some "terrain" you'll want to group it properly so that you can build it into a zone later. Select the square, right click it and click "Make Group". Then double click the group to focus it and repeat this step. This will create a group within that group.

The reason you do this is so that you can use the outer group to represent the zone and the inner group to represent Intersect collision (the ground). To do that, you will want to name the outer group to Zone001 and rename the inner group to Ground [Intersect]. Once you've done that, your Outliner should look something like this:

outliner groups

By default, everything within any group that represents a Zone will become a Static Entity model in the map. In this case however, the [Intersect] group tag in the name of the group inside "Zone001" tells the Map Builder that the contents of this group should also be made into Intersect collision.

Group tags are one of the main ways you'll tell the tool how you want the files built and what the groups represent.

With those groups setup and named appropriately, you've successfully made a very basic zone of a map.

Step 5: Adding a couple locators

The scripts included in the mod from Part 1 reference a couple locators to specify where the player and their car should start in the level.

The mod does not provide these locators as you're also going to create those with the Map Builder using one of its Special Components.

Go to File > Import and navigate to the "Components" folder next to the Map Builder's executable. From there import "Locator.skp" into your model.

This will attach an instance of it on your cursor and you can go ahead and place it down anywhere on the terrain you created in Step 3.

Now if you go to the Components panel and click the little house icon to bring up the list of components in the current model, you should see "Locator" in the list if you imported it correctly.

components home button

Now select it in this list and drag a second one out onto the terrain.

We're going to use these two locators as our player start and car start locators. You'll want to name one of them level1_homer_start [CarStart] and name the other one level1_carstart [CarStart].

The [CarStart] group tag used on these components tells the Map Builder to make Type 3 Car Start locators which, despite their name, are also used for character starts.

Now that they're named and tagged select both of the instances, right click and click "Make Group". Once you've made the group, name it "Level".

Make sure this group is in the root of the file and not inside the "Zone001" group.

Once you're done that, your Outliner should look like this:

locators in outliner

Step 6: Save again!

Make sure you save everything you've done so far if you haven't already.

Part 3: Configuring the Map Builder

Step 1: Creating the build files

To start, you want to create an XML file that will contain all of your rules for the Map Builder and a BAT file to actually launch the tool and tell it about your rules.

For now, just make a bare bones XML file that just has a Build element. These are used as the root of any rules file for the tool.

<?xml version="1.0" encoding="UTF-8" ?>
<Build>
	
</Build>

Save this file as "Build.xml" into the "_Assets" folder next to your SketchUp file.

Then make a BAT file that launches the Map Builder with "Build.xml" as a command line argument:

@"C:\path\to\LSHaRMB.exe" "Build.xml"

You'll need to manually replace the path with where-ever you put the Map Builder. Save this as "Build.bat" into the same folder when you're done.

Once those are saved, running Build.bat should work and you should get an output that looks something like this:

[12:58:35 PM] MESSAGE: Loading SketchUp SDK DLL (64-bit) 17.0.18899.0...
[12:58:35 PM] MESSAGE: Processing outputs...
[12:58:35 PM] MESSAGE: Processing file outputs...
[12:58:35 PM] SUCCESS: Completed in 25.2060558021864 ms.

You haven't told the tool to do anything yet so it hasn't actually created any output files. This is just to make sure that the BAT file is working as intended.

Step 2: Defining an OutputPath variable

The Map Builder supports defining custom variables and it also has several predefined variables that you'll be using in this tutorial.

That said, the first order of business is defining a couple custom variables for the working path and also for where your output files are going to go. You can do this using a SetVariable element.

This isn't technically required but its good practice to do.

These can simply go in the root element of the XML file you made in the previous step:

<!-- Store the folder this XML file is in as the root working path -->
<SetVariable Name="WorkingPath" Value="$(ParentPath)" />

<!-- Get the parent path of our main Rules file then go up a directory then into CustomFiles -->
<SetVariable Name="OutputPath" Value="$(ParentPath)\..\CustomFiles\art" />

Notice that this path uses the special predefined $(ParentPath) variable. This is a quick and easy way to get the path to the XML file setting the variable. The reason its used here is so paths in any XML file that use this variable are relative to this file, even if they're in a subfolder.

In this tutorial, we're going to be using just this one XML file but its good practice to use this for paths used in various files.

Step 3: Including the base Zone rules

Before you write any more of your own rules, you'll also want to include some of the tool's base rules. Simply add an Include element in the root node of the Build file you created in the last step and set the path to Zone.xml.

<!-- Use the ModelBuilderPath variable to easily fill in the path to the tool's folder -->
<Include Path="$(ModelBuilderPath)\Rules\Zone.xml"/>

This file contains all the necessary definitions to build Zones.

Notice that this path uses the predefined $(ModelBuilderPath) variable. This is a quick and easy way to include things relative to where the Map Builder's executable and files are located (like this base rules file).

Step 4: Specifying output files and zones

The next step is defining what the output files we're going to be building are. In this case you should add OutputPure3DFile elements for the Terra file, Zone 1 and the locators file.

<!-- Specify output files -->
<OutputPure3DFile Name="Terra" Path="$(OutputPath)\L1_TERRA.p3d"/>

<OutputPure3DFile Name="Zone001" Path="$(OutputPath)\l1z1.p3d">
    <!-- Tell the tool that this file requires the Terra file to work -->
    <!-- This allows it to place textures/shaders used in multiple regions in the Terra file to save space -->
    <RequiredOutputPure3DFile Name="Terra" Textures="true" Materials="true" Lights="true"/>
</OutputPure3DFile>

<OutputPure3DFile Name="Level" Path="$(OutputPath)\missions\level01\level.p3d" />

You also want to define some information about the map using a HitAndRunMap element and the zones using a HitAndRunZone element, telling each one to output in the appropriate OutputPure3DFile element.

<!-- Define the map -->
<!-- This gives you control what file the k-d tree goes in, the size of its tree nodes and how many DynaPhys are allowed in each node -->
<HitAndRunMap Name="Map" TreeMinimumNodeSizeX="20" TreeMinimumNodeSizeZ="20" TreeDynaPhysEntityLimit="10">
    <OutputPure3DFile Name="Terra"/>
</HitAndRunMap>

<!-- Define zones -->
<!-- While things can be output directly into P3D files, outputting them into a zone instead makes them get included in the map's k-d tree -->
<!-- Which is VERY important of course -->
<!-- We don't need to do this for our Level OutputPure3DFile though since it's just going to contain locators and no world stuff -->
<HitAndRunZone Name="Terra" Map="Map">
    <OutputPure3DFile Name="Terra"/>
</HitAndRunZone>
<HitAndRunZone Name="Zone001" Map="Map">
    <OutputPure3DFile Name="Zone001"/>
</HitAndRunZone>

With these rules in place, the tool will now build empty P3D files to those paths. That's progress but you still need to tell it what to put in those files/zones.

Step 5: Making a light group and vertex colors

Before you handle how things are going to be built, you'll need a LightGroup element and a VertexColours element that references it.

The former will build a light group that will be used to light objects with dynamic lighting in the world (typically just cars and characters) while the latter will use it to apply static vertex colors to your map's models.

<!-- Specify the Light Group and name it -->
<LightGroup Name="Level1">
    <!-- These lights are more or less equivalent to the "sun" light group in the original game's L1_TERRA -->
    <AmbientLight Name="Ss_ambientLightShape1" Red="89" Green="89" Blue="89"/>
    <DirectionalLight Name="Simpsons_sun_directionalShape3" Red="89" Green="89" Blue="89" DirectionX="0" DirectionY="-0.5" DirectionZ="-0.866"/>
    <DirectionalLight Name="Simpsons_sun_directionalShape2" Red="140" Green="140" Blue="140" DirectionX="-0.75" DirectionY="-0.5" DirectionZ="0.433"/>
    <DirectionalLight Name="Simpsons_sun_directionalShape4" Red="140" Green="140" Blue="140" DirectionX="0.75" DirectionY="-0.5" DirectionZ="0.433"/>
    
    <!-- Specify an output file and chunk name to build this group into -->
    <OutputPure3DFile Name="Terra" ChunkName="sun"/>
</LightGroup>

<!-- Specify VertexColours rules that reference that light group -->
<VertexColours Name="World" Light="Level1" LightAbsolute="true"/>

Step 6: Specifying a fallback material

Until your map has materials, you will want create a fallback material with a Material element that the tool can fall back to for faces that don't have any.

<!-- Make a white material -->
<Material Name="Null" Red="255" Green="255" Blue="255"/>

Step 7: Specifying input files

Now you'll want to specify input files using an InputSketchUpModel element and a couple InputPure3DFile elements.

<!-- Of course you want to input your Map's SketchUp file -->
<!-- Here we use the WorkingPath variable we set earlier -->
<InputSketchUpModel Name="Map" Path="$(WorkingPath)\Map.skp"/>

<!-- You'll also want to input a couple files from the original game -->
<!-- This will make sense in step 9 so stay tuned -->
<InputPure3DFile Name="L1_Terra" Path="$(GamePath)\art\L1_TERRA.p3d" />
<InputPure3DFile Name="L1_Level" Path="$(GamePath)\art\missions\level01\level.p3d" />

Step 8: Defining model output instructions

The next step is defining the instructions for outputting your SketchUp file using a ModelOutputInstructions element and a SketchUpModelOutput element.

<!-- Instruction set used for each zone -->
<ModelOutputInstructions Name="Zone">
    <!-- Use the instructions we included from "Zone.xml" in Step 3 -->
    <ExecuteInstructions Name="BaseZone"/>
    
    <!-- Set the vertex colors (lighting) of everything to the ones defined above -->
    <SetParameter Name="VertexColours" Value="World"/>
    
    <!-- Set the fallback material to the "Null" material created above -->
    <SetParameter Name="FallbackMaterial" Value="Null"/>
</ModelOutputInstructions>

<!-- Main instruction set -->
<!-- Execute all of these instructions on the InputSketchUpModel named "Map" -->
<SketchUpModelOutput InputSketchUpModel="Map">
    <!-- Add selectors for each group name -->
    <!-- Basically when that group name is encountered, we'll execute the instructions inside the selector -->
	<!-- "Exclusive" makes it so the selected group will only have these instructions applied to it -->
    <AddSelector Pattern="^Terra$" Exclusive="true">
        <!-- Each zone needs to Output to a Zone so it can be included in the k-d tree -->
        <!-- That includes the terra file since it can contain things like roads and fence collision -->
        <AddOutputZone Name="Terra"/>
        
        <!-- Use those instructions we defined above -->
        <ExecuteInstructions Name="Zone"/>
    </AddSelector>
    
    <AddSelector Pattern="^Zone001$" Exclusive="true">
        <!-- Same deal here but with a different output zone -->
        <AddOutputZone Name="Zone001"/>
        <ExecuteInstructions Name="Zone"/>
    </AddSelector>
    
    <AddSelector Pattern="^Level$" Exclusive="true">
        <!-- Since this group just contains locators, we can output to the P3D file directly -->
        <AddOutputPure3DFile Name="Level"/>
        
        <!-- As well as use more specific instructions (also from "Zone.xml") -->
        <ExecuteInstructions Name="Locators2"/>
    </AddSelector>
</SketchUpModelOutput>

Step 9: Borrowing from the original game

Now is where those P3D files you inputted earlier come in. You're going to want to extract a few things from them to place into your map's files using several Pure3DFileChunksOutput elements.

<!-- "EnvMap.bmp" is being copied from Input "L1_TERRA" P3D into our new Output "Terra" P3D file so car reflections work -->
<!-- This is placed at the start of the Terra file with Start="true" -->
<Pure3DFileChunksOutput OutputPure3DFile="Terra" InputPure3DFile="L1_Terra" Type="Texture" Name="EnvMap.bmp" Start="true"/>

<!-- Input Road Arrow Anims -->
<!-- This is REQUIRED for missions to work (though our map doesn't have any roads so they won't work yet -->
<!-- This is mainly here for the next tutorial that gets into adding Roads -->
<!-- These need to be placed after any Intersections in the Terra file so you need to specify AfterIntersections="true" -->
<!-- For that same reason, it is crucial that this is after your SketchUpModelOutput element -->
<Pure3DFileChunksOutput OutputPure3DFile="Terra" InputPure3DFile="L1_Terra" Type="Anim" Name="darrow" AfterIntersections="true"/>
<Pure3DFileChunksOutput OutputPure3DFile="Terra" InputPure3DFile="L1_Terra" Type="Anim" Name="warrow" AfterIntersections="true"/>

<!-- "coinShape_000" is being copied from the Input "L1_Level" P3D to the new Output "Level" P3D -->
<!-- Since this is just a mesh, you can really put it wherever you want as long as level.mfk loads it -->
<Pure3DFileChunksOutput OutputPure3DFile="Level" InputPure3DFile="L1_Level" Type="Mesh" Name="coinShape_000"/>

Step 10: Build and check it out ingame

Now it's time to run Build.bat again to see if it works ingame.

If you've done everything right, the map should successfully build and look something like this.

final product

You're done!

That's it for this tutorial. You're now ready to move on to the next one.