Guide:Creating a Mission

From House of the Dying Sun Modding Wiki
Jump to navigation Jump to search

This guide expects you to have set up a workspace and created a plugin project before continuing.

You are allowed to change the names of your mission objects, but just ensure that they are changed thoroughly. You are also allowed to copy items from "Assets/Resources/campaigncrusademissions" and edit them.

Setup

Inside your Custom project folder, create a new folder and call it "missions". Add a new folder inside it, and label it "test_001". This is where your mission will be saved to.

Next, open a new scene. This is where your new objects will go.

Landmark scenery

Create an empty GameObject and label it "LANDMARKSCENERY_TEST_001". This is where the mission layout will begin.

Do the following:

  • Reset its position.
  • Give it the components Landmark Scenery, Floating Transform, and Nemesis Fleet Spawner.
  • Add any number of ship flights from "Assets/Resources/flights" as children and enable them. Ensure none are overlapping.

Inside the Landmark Scenery:

  • Set "Asteroid Prefab" to "Assets/Prefab/asteroid_01_prefab".
  • Add any number of asteroids to "Asteroid Datums" with desired radius, position, and rotation for each.
  • Optionally, "Nemesis Angle" may be set.
  • Check "Override Landmark Pos".
  • Set "Star Angle" and "Star Distance".
  • Add any number of landmarks from "Assets/Resources/landmarks" into "Landmark Datums", with their distances and angles set.

Inside the Nemesis Fleet Spawner:

  • Set "Override Flight" to a flagship from "Assets/Resources/flights/federation"
  • If you do not want the flagship to spawn when the objective is complete, uncheck "Auto Spawn When All Objectives Completed"
  • Most missions have the time for the flagship to spawn increased when the difficulty is higher. If you would like to follow this, set the spawn delays roughly 20 seconds apart.

Inside the flights:

  • Set the difficulties to where they appear
  • If you want the flight to be there as the player warps in, set "Place Automatically".
  • The designation may be set if desired. Be aware that designations of child spawners will override this.
  • If you want this fleet to instead be a reinforcement, give it the Reinforcement Flight component and set their delays.

Inside the child objects of those flights:

  • You may set the shield, hull, and speed percentages (represented by a float value, 1 to 0).
  • The designation may be changed. If you want this object to use its parent's designation, only use "$".
  • If this is a target, give it the component Objective Target.
  • If this is a bonus target, give it the component Bonus Objective Target.
  • If this target should have an escape pod, give it the component Escape Pod Controller.

Save the Landmark Scenery object as a prefab and deactivate it.

Landmark

Create an empty GameObject and label it "LANDMARK_TEST_001". This defines some of the general info of the landmark.

Do the following:

  • Reset its position.
  • Give it the components Landmark Defended (or a class that derives from it), HUD Icon Landmark, HUD Icon Priority Target, and Landmark Line Renderer.

Inside the Landmark:

  • Change "Name Root" to "TEST".
  • Check "Is Available For Player Warp" and "Is Terror Mission Landmark".
  • Set the warp in radius min and max to 10,000 minimum; this will determine how far from the center the player ships are dropped off.
  • Set "Landmark Scenery Prefab" to the landmark scenery prefab you created.
  • Uncheck the randomize rotation checkboxes.
  • Set "Min Difficulty" to 1 and "Max Difficulty" to 2.

Inside HUD Icon Landmark:

  • Set "Icon Type" to Landmark.

Inside Landmark Line Renderer:

  • Set "Landmark" to the GameObject it is attached to.
  • Set "Culling Mask" to Skybox.

Save the Landmark object as a prefab and deactivate it.

Terror missions

Create an empty GameObject and label it "TERRORMISSION_TEST_001". This defines a mission objective.

Do the following:

  • Reset its position.
  • Give it the component Terror Mission (or a class that derives from it).

Inside the Landmark:

  • Set "Title String", "Battle Prefix", and optionally "Score Screen Objective Title".
  • Set "Short Objective Text".
  • If desired, the objective subtitle overrides may be set.
  • Set "Music Intensity On Activate" to 2.
  • If desired, the VO IDs may be set.
  • If you want an objective flight that the player cannot control, set "Allied Flight Prefab" to an empire flight.
  • If you want the player to defend this flight, check "Order Player Fleet to Defend Allied Flight".

If you want to add a custom bonus, repeat the steps with some changes:

  • Give the new GameObject the component Terror Mission Bonus (or a class that derives from it).
  • Ignore the first three strings.
  • Set "Icon" to "Assets/Resources/ui/icon_upgradetoken_01".
  • Ignore music intensity.
  • Set "Vo Objective Complete ID" to "Mission.BonusObjective.Complete".

Save the Terror Mission object(s) as a prefab and deactivate them.

Sortie template

In the project tab, at your mission's folder, right-click in an empty space and select Create > Sortie Template. Name it "MISSION_TEST_002".

In your new sortie template:

  • Set "Title", "Description", and "Header Texture" (a 2048x1024 image).
  • Set "Difficulty" to -1.
  • Set "Starting Landmark" to "First Terror Mission".
  • Add any number of area styles from "Assets/Resources/solarsystem" to "Area Styles".
  • Add any number of visual styles from "Assets/Resources/solarsystem" to "Visual Styles".
  • Set "Rewards" and "First Time Rewards". For the former, each ID corresponds to difficulty. See RewardDatum for more information.
  • Add the terror missions you created, or those from "Assets/Resources/terrormissions", to "Terror Mission Prefabs".
  • Add the terror mission landmarks you created, or those from "Assets/Resources/landmarks", to "Terror Mission Prefabs".
  • Set "Landmark Name Override".
  • If desired, set the banner title overrides.

Node position

All that's left is determining where the mission appears on the mission select screen. Open the Workbench scene in "Assets/Scene/Scenes" (do not save the blank scene you created), and in "#GALAXY_ROOT/GALAXY_ROTATOR/ROOT_Overworld", add a new blank GameObject with the name "POS_TEST_001". Move it to the place you want, but make sure its Y-position is 0. Write down the names of the nodes you want it to connect to, and save them for later.

Save the object as a prefab.

Creating and preparing an AssetBundle

Now everything is ready. Select all objects in your mission folder, and, in the AssetBundle dropdown at the bottom of the Inspector window, click "New...". Type in a name and press enter.

Build the AssetBundle by using Control-Alt-B, or right-clicking in the Project tab and selecting "Build AssetBundles". Once built, open the workspace's folder in File Explorer, go to Assets/AssetBundles, and copy the asset bundle into the folder where you are developing your plugin.

Now, open your plugin project and select "Show All Files" in the Solution Explorer window. Right-click on your asset bundle, and select "Include In Project." Next, right-click on your project, select "Add" > "New Item...", look for "Resources File", and give it a name. With the file open, drag your asset bundle into the window.

Using MissionLoader

MissionLoader is a plugin that makes the spawning of missions easier.

You will need the plugin downloaded, the assembly made as a dependency in your plugin, the line [BepInDependency("MissionLoader")] above your BepInPlugin attribute, and a using directive for the "MissionLoader" namespace.

Inside the plugin, create a void method named "SpawnOnLoaded" with no arguments. Add the following code inside:

NodeSpawner.SceneReady -= SpawnOnLoaded;  // Unhook as we don't want to repeat ourselves
AssetBundle bundle = AssetBundle.LoadFromMemory (YourResourceNameHere.assetBundleNameHere); // LoadFromFile will work for plugins directly inside the BepInEx folder, but not in Thunderstore packages
List<UnityEngine.Object> objects = new List<UnityEngine.Object> (bundle.LoadAllAssets ());  // Namespace usage for clarity
bundle.Unload (false);  // Unload since we don't need to read from file any more

List<NamedNodeDatum> namedNodeData = new List<NamedNodeDatum> { new NamedNodeDatum ("MISSION_TEST_001", new List<string> { "NODE_NAMES_HERE" }) };
NodeSpawner.FindAndReadyNodes (namedNodeData, objects);

And inside the plugin's Awake method, add the line NodeSpawner.SceneReady += SpawnOnLoaded;. What we've just done here is:

  • Hooked to a SceneReady event, which happens when all objects are truly loaded (unlike SceneManager.sceneLoaded which triggers when the scene is loaded but not yet ready)
  • When the method is called, unhooked from the scene
  • Loaded the asset bundle, loaded its objects, and stopped reading the file
  • Created node datums from our object names
  • Readied our objects for loading

Now the implementation is complete. Build the plugin and copy the assembly, plus the asset bundle, into BepInEx/plugins at your game's directory. If everything is correct, the plugin should load without error and you should see your new mission in the menu screen.