Looking to tell your own story in BATTLETECH? This thread is a guide on how to craft a story in to a Flashpoint (FP) using ModTek and other free tools. I will cover the basics of the FP system and how to get them loaded in to the game via ModTek.
The second post will cover advanced topics like spawning requirements, complex Event Results, failure Milestones and contextual conversation options.
One thing I want to say at the start, writing these Flashpoints is a lot of fun. It might take you a while to get it done, but others like @akodoreign manage to put them out incredibly fast. I want to encourage everyone to try and make their own FPs. I've only just got started pioneering the process. I'm sure with more people diving in and experimenting in ways I haven't, we'd be able to tell ever greater stories and expand the experiences possible with BATTLETECH.
Also, I know nothing. I've only been able to hack this all together with experimentation, a lot of help from other modders and asking questions to HBS staff when they had the time to assist on Discord. I'm sure something in here will be wrong or not quite correct, and something I think isn't possible probably is. So, take all this with a grain of salt, I've barely scratched the surface of this beast.
The Idea
First thing is "Why?" Why are you trying to make a FP? Is it to create a challenge? To tell a story? To give players a fun experience? For the challenge of creating something? The reason why you are doing this should be thought about at every stage of the process. Keep this idea in mind as kind of a "mission statement" or anchor that will shape how you form things from the choices the player can make to the kinds of missions you use.
Second thing is that Flashpoints are about making a decision. Either A or B, not A & B. Now, you don't need to have a branching choice in your FP, you could just as easily make a full FP with nothing but a single mission and conversation around it, or 4 missions with no conversation or choices. However, the choices you want the players to make, and where those decisions are, will greatly impact the amount of work that needs to be done. Doubly so if you have more than one FP Decision point.
If you make an initial split like "Joint Venture" the missions are on two separate branches for the entire FP. If you make a five mission FP with an initial "A or B" branch, that's ten missions to construct. The earlier the split, or the more splits you make, the more work that needs to be done with missions, conversations, rewards, tag tracking and anything else that makes one branch different than another.
The Tools
Once you have an idea and how the players choices will affect that idea, you can get to work actually building something. HBS has graciously included a set of editors in the game here:
Debug Mode
You're going to want to enable Debug Mode to allow quick turnaround for testing. A Debug Save populates all available FPs within 14-30 days and lets them re-populate quickly if failed. Be aware, don't leave this on all the time. It generates some default dump files and will mess with your PvP sync if the other end doesn't have it enabled too.
@HBS_Eck has created Eck's Debug Guide for modders.
What can Debug Mode get you?
simgame Debug Window
You can spawn 'Mechs whole, grant cash and rep/MRB ratings and more. You can't access this window in a non-Debug save.
combatgame Debug Window
You can enable "God Mode," auto-win a contract, dump info and more. This can be accessed in either Debug or non-Debug saves.
The Workflow
"This is a lot of crap! Where do I start?" is something you might be asking. I find it's best to create the Flashpoint file in the editor, formulate your FP structure and branching, test that format with placeholder conversations, missions and rewards and then fill in the rest as you wish. Getting a solid FP structure and testing them out to make sure you can go from one link in the chain to the next is essential and should be robustly stress tested to make sure you won't leave a player stranded with a bad conversation, tag or branch that goes nowhere. It's really easy to make a FP that links to a bad/missing item and enter a shadow-zone where Farah or some other crewmate has gone invisible and you can't complete or abandon the FP to get them back. I've done it many times...
The Templates
HBS has included a bundle of templates for just about everything in the game, including FPs. These are the same templates the stock FPs are built from and their conversation filenames still reference the type they were built from. These templates are great examples for almost any combination of FP branches from early/mid/late splits, optional objectives and even three-way splits. You can also use a modders FP files as working examples. The stock FPs are kept inside an asset bundle, away from easy access. They can be extracted and referenced, but I'm not going to discuss that in this post. The default templates are located here:
THIS IS NOT WHERE YOUR FP NEEDS TO BE TO LOAD IN TO THE GAME.
I'll address this down in the ModTek section below.
The Stand-Alone Editor Folder
While this is an optional step, I highly recommend doing this before you start editing anything.
There's a really big chance you might insert something in to the stock folders or edit something you shouldn't have if you work out of the game's running \StreamingAssets\data\ structure. However, the various editors assume this structure and pull items from it. What I did was copy everything I needed out of the game's folders. This also ensures any HBS update or steam/GoG/etc validation doesn't remove your files.
Before you copy these HBS folders out of the \BATTLETECH\BattleTech_Data\StreamingAssets\ you need to make sure you copy the folders inside \data\ without the "assetbundle" or "maps" folder, these are massive and you don't need them. Removing them cuts the Stand-Alone Editors to about 150mb from many gigs in size.
Afterwards, I made a desktop shortcut for the FP editor at the new location. This makes it easy to use in the isolated location and my actual game files stay unaltered even when I make mistakes at 3am. You do need to make sure you copy over all of these again anytime HBS pushes an update.
The Flashpoint .json Structure
The Flashpoint Editor opens a FP file, "fp_TEMPLATE_initialChoice.json" from the location above. This file contains:
In the FP editor it looks like this:
Editing FP Files
HBS Formatting for FP files:
Changing your internal name has cascading effects on the resulting files created and associated with this FP. The first step in editing your FP should be giving it a unique internal name you don't intend to change. Remember, this isn't the name shown to the player, ever. This is just the name the game uses to categorize your stuff from another FP.
Set the Location Requirements (Employer, Target and Planet)
The next thing you would want to define is who is this FP fighting for, against and what planet it starts on. The section labeled "Location Requirements" shows the "Potential Employers" which can be edited and selected from the list of faction tags. I've not experimented with multiple potentials yet.
The Target Faction is a drop-down list, take note of the spelling and capitalization of factions on this list. You will need to copy these exactly as shown for later when you define your contracts in milestones.
The "Required Tags" is where you would define what planet it starts on. I believe it might be possible to start a FP at one location and move to others, but I haven't tested this. You can find the tag you need by opening up the data/starsystem folder and opening the planet's .json file you need. You will see a tag with the planet's name on it:
Set the Optional Restrictions
This can be done near the end of your process. You might want to check some of them right away, but I don't think the game or the editor cares too much if what is selected is accurate. You could check "Allow Refit" and then make a FP with all consecutive drops with no refit pause in between. Make sure your final product is accurately reflected in your optional restrictions.
Set the Short Description
This is the text at the bottom of the title card. This is should be short and sweet and try to entice the player in to accepting your job. Like the optional restrictions, this can be saved for later to make sure it accurately reflects the final product. You may want to look at other stock title cards to get an idea of what info they deemed important, sometimes less is more.
Setting Conditional Requirements for FP Spawning
You can set FPs to only appear if the player's save has or doesn't have certain tags or values like "MRB Rating greater than X" or must have/not have "ALLIED_FACTION_Liao" and I'll cover that in the Advanced Editing Post below this one. For now, it's better to just get your FP structure laid out and tested before adding restrictions on it appearing.
Setting the Icon
A picture can say a thousand words and HBS made one title card icon to represent all FPs from Joint Venture to ones featuring Morgan Kell and Justin Allard. You don't need to make a custom icon for every FP. I'm going to recommend it though. This will help clearly separate stock FPs from modded ones even if a player has left the game for months and comes back to it, forgetting what was stock and what was modded, then makes a bug report about a non-stock FP.
The format for title card icons are:
Note the dark bar at the "bottom" of the image, this is to make the "Flashpoint: Expires in X Days" stand out against a similarly colored background, this bar is 24px tall and I think the in-game bar is roughly 24 or 25px high. There is also a light blue "Active Flashpoint" bar that replaces the expiration date once you accept the job, so I recommend a darkened or full black bar so any status message pops out and is easily readable.
The Milestone Sets Structure
The Milestone Sets (MS) are the most important part of the FP. If the FP file is the "cover" of a choose-your-own-adventure book, the MS .json is the index and the breadcrumbs at the bottom of the pages. The MS file such as "ms_fp_TEMPLATE_initialChoice.json" contains all of the triggers, event results, branches and mission parameters for the FP.
The MS file is created by the FP Editor alongside your FP file when you save it for the first time. As it's created by the Editor for you, it takes care of a lot of the naming and formatting. The "Reorder Milestones by Links" will format them automatically. MS files are .jsons stored in and read from:
In general, MS start a 001 and increment up until they branch out. Each branch increments the first digit by one. In the initialChoice template, where the branch is at the start, we see this:
At this point, the best thing you can do is to open up the FP Editor, pick a template like "Initial Split" and browse through every MS by clicking on one to highlight and then hit "Edit" to see more details. Going through these first, then looking up how each data field is used will help you put it together better than reading this guide strait through.
This initialChoice template would have us start, go in to a "TalkChoice" MS where it would call a conversation, have us pick a Flashpoint Decision inside that conversation and set a unique tag. Then, the Branch MS would trigger and pick one result that matches the tag applied in the conversation, sending us on either the 100, 200 or 300 branches. The 100 and 200 branches have missions, talks and other MS labeled "A" and "B" respectively. You can have a "C" branch, and maybe even more, but the workload starts to become cumbersome.
Inside each MS, there is an "Action" that must contain a link to the next one in the chain. You can have multiple actions in a branching MS that link to different MS but make sure your use of Required/Excluded tags is logical sound and won't allow double dipping. The three kinds of actions that can set a next milestone link are:
You should edit and create MS inside the FP editor, but you can copy/paste and edit MS whole or in part in the .json with a text editor. So far, I create the MS and names in the editor, click "Reorder MS By Links" and then save the FP and exit the editor. I then open the ms_fp_yourStory.json in Notepad++ and correct the rewards MS numbers as they are bugged and get re-numbered. If you don't like the default numbering scheme, you can change that manually too, but be careful. Once that's edited, I re-open the FP editor and click Reorder again, if the only errors look like this:
For each reward MS you have, then the rest are good as is and you can hit "Cancel" to preserve your formatting. If you see other errors like these:
You got some more basic problems and the editor can't find missing links in your chain.
NOTE: BUG FIXED IGNORE THIS -There is a bug with the Reorder Links Button, it doesn't recognize "Rewards" MS that come after "Complete" MS and you can just hand edit them back to 100/200 series as needed using your .json editor.
Here is the pop-out Milestone Editor Form, opened by clicking "Edit" after highlighting one of them in the MS list at the bottom of the FP editor. The Id and Name are somewhat hard to edit and grasp at first. Changing the name, then hitting the "Reorder Milestones By Links" in the main FP editor window will update the Id to "ms_(FP Id)_(Number)_(Name of Milestone)"
The "Scope" of these is usually "Flashpoint" to tell the game it takes place in the realm of this specific FP. The Scopes cover the areas you'd expect in that the "Company" scope covers the kinds of things like tags you take with you after events or completing the Campaign or FPs. The "Mech" or "Mechwarrior" Scopes would get used in Argo Events to wound or impact a specific pilot or 'Mech. For FPs, the two scopes that are the most used will be "Company" and "Flashpoint." At first, just keep these to what the templates use, which is usually "Flashpoint" for the MS Editor Form.
Towards the bottom of the MS Editor Form, there is a list of "Results," these are the core of what happens during this MS and where to link to the next MS in the chain. The titles of these events are declared in their "Scope" in the MS Event Results Screen.
Keep in mind, Company Scope tags and status modification edits like Mech/MedTech numbers will carry on after the FP is completed or abandoned. If you are not careful to set some of these things as temporary, you can permanently alter the players Argo Tech crew counts, morale, cash and even make cast members go invisible forever. Use these carefully and try to test them thoroughly to make sure anything you alter can be undone in a reasonable time.
The MS Event Results Screen
This is what you see when you hit Add/Edit a MS result. In this case, there are two things this Event Result does:
First, at the top, there is the Scope of this Event Result, "Company" in this case, no tags are added or removed and just below we see the "Random Scope" area. This is a LIE. This area is a "Required Scope" area, not "Random." This is where you would check for if the player has/has not certain tags or comparisons such as "Morale Greater Than X." This area is where your FP Branch MS detects which fp_choice_x tag the player has been given and where to go from there. This is an incredibly important thing to pay attention to and below I will show you how the branching works.
Within this Company Scope Event Result, the first Action sets up the details of the currently available contract. You can see the details of it on the lower right. There are two different Actions that generate a FP contract.
A "Flashpoint_StartContract" does not need a "System_ForceDropshipRoom" Action as it's implied and does that for you.
If you are going any kind of drop restrictions (Min/Max Tonnage by unit or Lance), I'd recommend you not drop them on a player as "Flashpoint_StartContract" or else they may be forced in to a DropShip Equip screen they can't exit, with no valid units to select and can get stuck. You can still do this, but make sure they are very well informed before entering a mission chain they can't back out of.
Currently, I don't believe it is possible to safely set a "Flashpoint_AddContract" that is also on a kind of timer that would force-start it once the timer expires. I tried this for "The Raid" and asked the devs if this was possible, but while it might be, it's an incredibly risky implementation of tags, events and other parts that shouldn't be used in such a way as it risks harming the save. The devs did not recommend I use it and I agreed.
Flashpoint_AddContract/StartContract Data
The Flashpoint_AddContract sets up a lot of essential items for the contract it generates. It however, is not the entire contract. First and foremost, it must point to a contract .json file in the "Contract Name" entry. You can just use a default contract found in the \data\contracts\ folder as a placeholder. I made sure to pick some very low difficulty ones from the FP Reference Sheet that had the right type of contract (Assassinate, Convoy Assault, etc) So I could get an idea of how the FP flow and branching works before I take the time to customize the contracts.
Next most important thing is going to be the map this takes place on with "Map Name" and "Encounter Guid" defining what map, and which part of that map to use. This is where the spawn points, buildings, convoy routes and other map layer stuff gets selected. I can have a contract.json that is a "simpleBattle" but that .json cares not what map it is applied to. You can give it a valid "Map Name" and if available, an "Encounter Guid" to apply that contract.json to. If you leave both of them blank, the game will use a fallback default map every time. Use my FP Reference googleDoc's "Encounter Layer" sheet in the "References and Resources" tab to pick from the possible combinations of map + encounter type. You will see some "simpleBattle" encounters have up to 4 different possibilities on a single map. If you want to use one of those that isn't the default or first entry, paste that EncounterLayerGUID in to the "Encounter Guid" section of the Flashpoint_AddContract Data, along with the corresponding Map Name.
Now that you have a contract.json and the map+encounterLayer it takes place on, you can copy/paste the Employer and Target Factions from the main FP screen. Spelling, spaces (none) and capitalization are critical here, I highly recommend a strait copy/paste and make sure no leading or trailing spaces get inserted. You can have these be different than the base FP's factions, but be careful. This would be used for you betraying your employer for the enemy, or hitting your own target, that kind of thing.
Optionally, if your contract has a special Employer's/Target's Ally Lance appearing (by default only some Target Acquisition contracts can do Enemy Allies) you set that here too. However, I ran in to a number of bugs getting this to "stick" on to the contract and to be sure, doubled up that info where it was present in the contract.json for that mission.
The Difficulty is out of 1-to-10, with 1 = 0.5 Skull and 10 = 5 Skull contracts in-game. This overrides the base difficulty setting in the contract.json, as they are only formatted as Easy/Med/Hard (2/5/8) and I'll address that later in the Contracts section. Normally, this difficulty will be the same as what you declared your FP to be and the game will scale the payments as appropriate. This difficulty is what the pay rate for the contract is built from in addition to the type of contract!
Next Milestone ID is exactly what you think it is. It defines which MS to link to next, if the mission is a success.
Failure Milestone ID is the same, but for when you fail the primary objectives or withdraw from the mission. I'll discuss this in more detail in the next post below.
Conversation MS
So that covers a mission, the map it takes place on, and where to go in the MS links once completed. But what does a conversation MS look like?
This is the ms_fp_theRaid_104_TalkChoice Event Result. It has two Actions:
You will need to open the ms_fp_yourStory.json and hand enter the convo GUID in to the space provided!
Where it says "value" : "9cc52ed03b2514c7432b5978", will likely be blank when this is new and just paste your Conversion's GUID in between the quotes. Once the convo ends, the game will go to the next MS set in the "Flashpoint_SetNextMilestone" statement. The most important conversations in your FP will be the ones that set the branching paths determined by your Flashpoint Decision options in the convo. Once the convo with the FP decision is over, you go to a special "Branch" MS.
In The Conversation segment below, I'll show how the FP Aid: FP_choice_placeholder.bytes can be used as a placeholder until your proper conversion is written.
Branch MS
The Branch Milestone is a kind of filter. It will check for some default tags like "fp_choice_a" or "fp_choice_b" and have different Event Results for each. Here is the Event Result in the Branch MS for "The Raid" that sets you down the A branch.
Take a look at the top, it has a Scope of "Company" and a Random Scope (really "Required Scope" and "random" is an error) of "Flashpoint" with a Requirement of "fp_choice_a" in the Required Scope. This means, to get to this Company Event Result, the Flashpoint Scope must contain a tag of "fp_choice_a" and that's how you start down this FP's "200_A" branch. In the previous conversation, it is possible to pick up either "fp_choice_a" or "fp_choice_b" or pick up none of them at all. I used this "no tag applied" setup for an early exit, allowing the player to take the A or B branch as an optional objective.
Here is that early exit MS Event Result, same Company Scope and FP Required Scope as the one above. However, the requirements are in Excluded Tags, which means you "must not have either fp_choice_a or fp_choice_b" in your FP Scope to get here. I could have also used a Requirement Tag of "fp_choice_c" instead, but when I built this, I didn't need to add a third tag. In the end, I did need one for some advanced conversation filtering, but that's for later in the advanced editing post.
The templates usually include this cancel path, but honestly, I don't think most FP's need one. You're really going to be pushing the player to complete the FP. Once you get in a few missions, offering them an out is kind of a red herring. If they fail/abandon it, it goes back in to the pool to try again. If you have a "Cancel Complete" it will "Finish" the FP once and for all. If you only want to give the player one shot at something, this is where to use it. Use "one shots" sparingly, probably for a great reward like a AS7-D-HT or a pair of Gauss Rifles and ammo.
Complete and Reward MS
Once it's all said and done, Darius usually puts everyone back to work and now you hit the completion Milestone and your reward. At the top, you will usually set some Company Scope tags to signal this company has completed this FP and took a specific branch.
The aptly named "Flashpoint_CompleteFlashpoint" declares it over. Here you set the final "Reward" MS to point to and then if you want to override the default reward you set in the FP json on the main FP editor options. In this case, the A branch gives more payout than the base and I overrode that to point at my A branch reward .csv file. If the default reward is what you want, leave the override blank.
If this is a "Cancel Complete" the "FP End Type" would be "CompletedWithoutReward" otherwise it seems to be left blank by default.
The "System_ForceDropshipRoom" to "Ship" just sets the menu back to the main Argo screen once we are done with the reward issue.
The Rewards MS does not set any loot rewards!
Those are defined in whatever .csv file you pointed the FP or Rewards Override to.
What the Rewards MS does set is any non-loot items like C-Bills, Morale, Reputation changes and other "status" type numbers. These are in a specific format, the same kind of format the Event Editor uses and if you need one for reference, you can check stock events that modify that value in either the .json or in the Event Editor. This reward shown has:
It pays out 3,900,000 C-Bills, lowers your Rep with the AuriganPirates by 30 (this is in addition to the Rep loss from contracts taken in the FP), adds +1 Morale and sets the "Black Market Access Display" to -1 or off. This FP dealt with raiding the Black Market and once you finish it, they are quite pissed and this is part of the steps needed to remove the players access. Note, in the background in the MS Editor Form, there is a second Event Result that is (Temp), this one sets the temporary time for the Market to not show back up. If you look at the top, you will see a list of tags added and removed. These deal with Black Market, mainly shutting it off and once it can come back on, giving the players company a "BANNED" status to let only the most expensive offer give them renewed access. It was worth it, or at least I think so. Main thing is, everything this FP does with the BM is actually temporary. It might take 666 days before you are available to get the "Banned offer" to restore access, but I'm not permanently cutting a save off from what is a pretty big feature in the simgame.
I'll cover Temporary Event Results in the Advanced Editing portion below. What you have above is the heart of the FP system. You have a set of Milestones linked together with a branching path of conversations, missions and finally the rewards. That's how you assemble a basic Flashpoint in to a playable state.
The Conversations
The main page of CWolf's ConverseTek (CT)has a general use guide and for FP's your conversations are going to take place in the "Conference" room as set by the "Talk" MS that calls it. Most of what goes in the conversation is the same as the CT usage guides and videos on CWolf's page. I'd recommend calling cast member by "CastID" over the harder to read "SpeakerID" and have made a chart of the common ones in the CastID/SpeakerID for Group Conversation of the FP References Sheet in the Resources and References tab. This isn't a comprehensive list, just what already appears in the stock game. You can type in any other castID and it will appear in the chat box just fine and it will show their Name/Title and portrait as defined in the castdef.
Setting a Holoscreen Image
Adding the Action "Set Battletech Viewscreen Image" and enter the filename of the image you want without the "uixTxrConv_" prefix in front. The sheet after the CastID/SpeakerID is a list of all the stock images you can call. You can add custom Holoscreen images and I will cover that in "Original Assets" below.
There is no stock way to "clear" the Holoscreen without error that I am aware of. If you call a image it can't find, it will display a clear screen. I don't like this method and so made a "screenoff" empty image file as part of the Flashpoint Aid: "Flashpoint Stock Photos" mod that I highly recommend using for your FP.
The custom castdef, Holoscreen image and the instructions on the CT git for contextual responses will get you here:
NOTE: Once you use a "Lock Camera" Action, you must manually assign any further camera changes in the scene. I don't know if it's possible to return the camera to "Normal" mode in CT at this time.
Setting a Flashpoint Decision Response
The big thing unique to conversations in FPs is the Decision Choice that takes place somewhere in the FP. These are responses as such:
This gives them the blue color for "[Flashpoint Decision: Make a choice]" and then your players "spoken" response. In general, you don't have much room for responses and the brackets eat up even more space, so try to keep them short. Once you have the look down, you going to have to apply a Flashpoint Scope "fp_choice_x" tag to that dialogue branch. This can be applied to the response, but HBS does it to the first Node after the choice.
ConverseTek Action: Apply a Flashpoint ScopeTag
This is basically saying "Add to SimGameScope: "Flashpoint" the tag string: "fp_choice_a" and this is usually done to a Node in HBS's examples. It can be applied to a response as well and should work.
To make this easy for everyone, I've made a placeholder conversation, check the Resources and References segment above for Flashpoint Aid: FP_choice_placeholder.bytes which is in a .zip file at the end of this post.
All you need to do is D/L this file, paste it's GUID "9caaf9ff484fe7d2823c5d7e" in to your TalkChoce MS Conversation value and you should have a working conversation that can apply the tags needed for most default Branch MS.
The Contracts
The contract .jsons can be edited to make custom missions within their general type. A "SimpleBattle" isn't going to become a mutated "Defend Base" no matter what kind of cut/paste hack job you do in the .json. This is an incredibly limiting factor at this time and I don't know if it can be bypassed yet.
This is because the contract .json is a map agnostic file. It specifies an existing contract type (SimpleBattle, Rescue, Destroy Base, etc) and that calls a specific EncounterLayer for the map selected. This layer is part of the map files and includes the coordinates for spawning locations, patrol routes for AI and everything else needed to run that type of contract on that specific map. Currently, we don't have an easy way to edit and create EncounterLayers and associated files, Mission Control by CWolf is very close to becoming this tool.
So how do we go about customizing the missions we have? First, you need to figure out which type of contract you want to build from. Then, I'd recommend selecting a map. You need to make sure the map you want had the appropriate EncounterLayer for the contract type. You can check the EncounterLayer (Map+Contract) of the FP References Sheet in the Resources and References tab to check maps sorted by contract type. I'm usually searching for a specific Biome (Lunar, Tropical, Highlands, etc) and make a list of maps available in that contract. Watch out, some maps or Biomes only have one possible setup. A Lunar Rescue for example only has one map available, but a Lunar Destroy Base has two. Still, that's only two possible Lunar maps where Tundra has four. Remember, some maps+contracts have up to 4 different EncounterLayers on a single map and they can all take place on drastically different terrain layouts even if they are on the same Biome and larger map space. The EncounterLayerGUID can be pasted in to the Action Data if it's not the first default entry for that map to use the other layers.
The next biggest thing we can customize are Optional Chunks. Some Defend Base contracts have APCs that turn on turrets, most don't, some Battles have a second Lance, others are just four units. These can be turned on and off by setting their Optional Chunk to "true" or "false" and what contracts have what chunks turned on or off can be found in Contracts of the FP References Sheet in the Resources and References tab above.
As a placeholder, you can find the stock contract that has all or most of the optional chunks you need turned on and then place that in your Mission MS and along with a map. You might have to go through a number of maps until you find one you like as enemy spawns, extraction zones and of course the terrain itself greatly changes how easy or hard that contract will be. A "SimpleBattle" with two far off Lances at the players 2&10 o'clock a mountain in between them is going to be handled much easier than the same two Lances spawning at 12&6 with no intervening terrain or cover at player spawn.
Now you have a general idea of how a mission will play out and maybe narrowed down the possible maps to 2-4 candidates. You can either take a stock contract .json and edit it, or build your own from scratch using the Contract Parser Tool in the edtitors folder alongside the FP editor. I'll cover editing the .json directly below the parser, but recommend using the parser first.
Contract Parser
The Parser takes a template .txt file and turns it in to a fully qualified contract .json for you. I recommend this method for all contracts except "FireMissions" (Target Acquisition) as the parser we have doesn't handle them at this time. HBS included all the stock contracts and stock template .txt files for us here:
@HBS_Eck made this Contract Parser Guide that goes in to far more detail about the specifics of the contracts.
Here is a copy of one of my .bat files, with the file path changed to reflect my person Stand-Alone Folder:
I edited the "..\..\StreamingAssetsSource\design\contracts" line to reflect my file-system structure and running this .bat file will parse all contracts found in the entire design\contracts folder. This is usually a bad idea. I don't need to parse every possible contract as HBS gave us all of the stock ones as .txts and .txt templates. What I did was make my own folder and had it parse those:
This makes it easy to find my output and not regenerate a ton of stock contracts every time I need to run it. On the first you will get at least 1 warning, that it needed to create a custom output folder as "amechcustoms" or "yourfoldernamehere" will not exist in the data\contracts folder already. Here we see two random design\contract files I put in to my custom design\contracts\amechcustoms folder and they pop out as valid game ready .jsons on the right inside my Editor Stand Alone Folder\data\contracts\amechcustoms folder created by the parser's first run above.
For the next three sections I'm going to notate these for both the .json and .txt templates using the DefendBase_BreakthroughBrink.json, DefendBase_BreakthroughBrink.txt and DefendBase_Template.txt as an example except when special FP options are needed.
Editing Contracts for Flashpoints
At the top of all the files we got our basics, ID, Name and Difficulty. FP contracts ID and Naming Conventions:
For a first mission, no branching yet:
"shortDescription" or [ShortDesc]
&
"longDescription" or [LongDesc]
Oddly, these are flipped. The Short Description is the paragraph in the negotiation and loading window. The Long Description is the one or two liner that Darius usually gives you underneath the full description.
See the "{TEAM_EMP.FactionDef.Demonym}" this allows a procedural contract to ask "Who is the employer and what do I call them?" and another one is present for the target faction who is the OPFOR. You can leave these, or just write in manually as this FP has those fixed in the MS Action Data above. I chose to manually put the faction's names in so I could read the text naturally for checking.
"salvagePotential" or [Salvage]
This must be a multiple of four! I also don't think a value higher than 28 is found in the game. The game also doesn't let players pick priority salvage over 7 (7/28?) and if they have "Generous Salvage" on they might even see 8/?? but only get to pick 7 items priority. Pay is set by the Difficulty set in the MS Action Data and the contract type.
FPs contracts need some special settings to separate them from normal ones. They take up a special slot at the top of the contract window, shouldn't show up in randomly generated contracts, usually don't have any special requirements on the contract level like min/max Employer Rep. and so on.
This clears any specific requirements usually found in a procedural contract like Rep. or MRB ratings.
This gives it the blue top slot in the contract selection screen.
This is normally "STANDARD" but this is for a FP, so it gets a "MID_CAMPAIGN" scope.
Total Lance Size, Lance and 'Mech Min/Max Tonnage Requirements
Not listed in the design templates, but present in the final .json file are parameters for setting the total Lance number, or Lance and individual 'Mech Tonnage restrictions. I'm going to have to use a different file's data for this, as a generated contract doesn't use these and they are not formatted in the template.txt.
This one is pretty strait forward, want them to only be able to take two units? Change to two, don't go over four. This number is including any forced ally 'Mechs you put in player control like Kamea or Mastiff from the SP tutorial missions. If you want allies to be present on the map and controlled by the AI, that would be in a different section below.
We see the "lanceMinTonnage" and "lanceMaxTonnage" set the total mass for all of the players units added up. you could take 320t either by 3x 100t KGCs and 1x 20t LCT or 4x 80t VTRs as long as it adds up to 320t or greater.
WARNING: The game doesn't like "lanceMaxTonnage" less than 120t for 2-4 slots. This 100t Max is OK for a SINGLE slot deployment (including forced units below)
With "mechMinTonnages" and "mechMaxTonnages" in the example above, each of the four units the player can bring must be 50t or less. It might be possible to edit each of the four values in the array, but I haven't tested that yet. I would assume it should work if you set up:
"mechMaxTonnages" : [
25,
50,
65,
85
]
It would allow a one slot with no greater than 25t, 50t, 65t and 85t respectively. You propably could mix and match Lance and 'Mech min/max limits but it starts to get confusing to explain to the player. I'd also consider following the guideline brackets set by HBS in the SimGameConstants.json for how to set your restrictions in the FP.json settings:
In the main FP editor screen, where it says "Unit Drop Hint" and "Lance Drop Hint" you would match your hint to whatever tonnage limits are in your contract. This may make unfortunate expectations by the player. If they see "UnitDropTonnageHint" : "Light", and think "Oh, that's 50t or less. I'll ready my CN9's..." and they get hit by a 35t or less limit, they might be equipped for that mission and have to abandon the FP.
Try not to force consecutive drops with new tonnage restrictions in the consecutive mission! What I'm saying is, don't let a player launch thinking nothing is different and then suddenly forcing them to drop with <40t immediately without a ton of forewarning before launching the first non-consecutive mission. You might want to tell them the exact limits while they are able to refit and pass time in case they misjudged the restrictions. Given there is no way to exit the DropShip Deployment window, if the player has no valid units readied, they are stuck.
Try to give them time before a special restriction to ready the appropriate units. Now, if your FP is all one single restriction across all missions, you can do that as long as you warn the player in the initial conversation before forcing a mission on them.
The weather and time of day effects are set in the contract, left alone it will pick a random valid Mood for the biome. This is also not editable in the template.txt. You must make sure you have your Biome set in the MS before setting the Mood here, or else it will throw an error and default to a fallback. The list of Moods per Biome can be found in the MoodIDs page of the FP References Sheet in the Resources and References tab above.
Further Flashpoint Options Not In Template.txt
SUPER IMPORTANT LINE TO ADD!
"excludedFromProceduralGeneration" : true,
You need this set to true to exclude this FP mission from being generated outside of the FP! Always double check every contracts "excludedFromProceduralGeneration" statement before releasing your FP.
When you are making a consecutive mission, you must remove the players ability to negotiate, cancel back out in to the simGame and set a fixed negotiation rate for them as below:
Editing Objectives
The "contractObjective" or [ContractObjective] section is the general single objective shown in the loading screen and also becomes populated with a default list of "objectiveGuids" which are unique Ids for the various sub-objectives like "Defend Industrial Laboratory" or "Destroy the Enemy Vanguard" that make up parts of the larger objective. Again we see the MadLibs statement used here "Defend a {TEAM_EMP.FactionDef.Demonym} R&D Facility" and this can be left in place or you can change this to plain text of whatever faction you want.
Right below that is the "objectiveList" or "// Battle Objectives" segment that details each objective and any bonus rewards for completing them.
While this list may always be a mile long, not all of these objectives are used in every contract, they can be tuned on and off in the next section, "Editing Optional Chunks" and the important things here are editing the "title" along with if the objective is primary for the mission along with any rewards for completing it. Look at the "Ensure All Buildings Survive" Objective above. There is no information about how many building this is, what buildings are chosen or how much HP they have, what exactly triggers a pass/fail and other qualifications. These are part of the EncounterLayer and can't be edited easily at this time. What we can edit is "isPrimary" : false, and changing that to true would mean a single building loss is a failure. There is some Building statements in the contract, but I haven't explored them yet. The results should look familar to you if you've looked at the MS .json or other Event Result screens. This uses the same format in the "OnSuccessResults" and "OnFailureResults" as MS and Events in the FP and Event Editors.
This means you can add or remove Tags, edit cash payouts by either % (as the default examples show) or by an absolute value and even do things like add/remove MedTech or MechTech levels. You should be able to assign whatever reward or penalty by using the same formatting from Event Results you may have already used in the FP or an Event.
Editing Optional Chunks
This contract has APCs appear that can turn on Turrets, it also doesn't have a 3rd wave of OPFOR appear. Most Base Defense contracts don't have one or the other or either. This is where we can turn these "Chunks" of the objective list on or off.
Inside this "chunkList" the chunk "Chunk_EscortAPC_DefensiveTurrets (Bonus)" is set to true and the chunk "Chunk_Wave3Attackers (Bonus)" is false. This is how you control which Lances will spawn and if other special events like turrets, DropShips and APCs appear in the contract. The Contracts of the FP References Sheet in the Resources and References tab above has most of the optional chunks listed, but is still incomplete at this time.
Editing Lances
Now that we have the objectives turned on or off as we need and the contract loads as a FP formatted one, we need to pick our OPFOR and if need be, allies and turrets. You can use any combination of generated Lances like a normal mission, manually assigning all four units in a Lance or a mix of both. This is up to you with what kind of story you want to tell or choices you want the player to make. You could bump up or down the difficulty of a generated Lance, manually assign a KGC in one slot of a low difficulty Scout Lance, or set all four units to custom 'Mechs you've designed for this FP, driven by custom pilots you tuned for each 'Mech.
The above example has the "Lance_Enemy_Wave1Attackers" and they are generating an entire procedural Lance. "lanceDefId" : "Tagged", sets this in motion and then below it you set the Tags you want that Lance to look for or exclude. In the example, it is looking for a Lance with the lags "lance_type_battle" and "lance_type_notallvehicles" with the difficulty scale of the Lance determined by the contract difficulty above, for FP's this is set in the MS Event Result Data for that mission. If this was a 10 Difficulty FP, it would look for lancedefs that meet all three of those conditions, as there is no further exclusions. Some of the valid options would be "lancedef_mixed_d10_dynamic_assaultBattle1" or "lancedef_mech_d10_dynamic_assaultBattle" and note that the second contains no vehicles where the first does, but none of them are all vehicle Lances. You can also tune up or down the difficulty of a Lance relative to the contract's difficulty with "lanceDifficultyAdjustment" : 0, and set to -2 would pull a lancedef 2 levels (one whole skull) lower. The "spawnEffectTags" is where you could set Lance-wide effects like starting at 50% armor using this example from another contract:
To use a "Manual" Lance, replace "lanceDefId" : "Tagged", with "lanceDefId" : "Manual" and it will ignore the Tag filters and only assign what you enter. Each unit would need these lines replaced:
You then repeat this process for each Lance and unit in play. You can assign 'Mechs and pilots to the player Lance in the same way, like Kamea in the campaign or the Hatchetman and pilot in Joint Venture. Keeping a Lance as "lanceDefId" : "Tagged", with Tag filters, and then manually assigning a single Lancemate would let you assign that one member and then let the Lance generator fill out the rest procedurally.
Editing Dialogue
The Dialogue is fairly strait forward, at first. You can copy and paste whole sections and just replace the "selectedCastDefId" or [Cast] with whoever you want to do the talking and edit the text as you wish. I don't recommend making these too long.
A problem arises with the mission finishing text. Some missions finish when you enter a Extraction Point, others end where you stand when the field is clear of all forces and objectives have been completed. This is where "Dialogue Buckets" come in. This is a special "bucket" or "pool" of chat boxes for a situation. We generally only need one.
Dialogue Buckets and DialogBucketDef
The line "overrideAutoCompleteDialogueId" : null, in a contract can be replaced with a custom DialogBucketDef for when your mission autocompletes. Some missions don't autocomplete or autocomplete by default (Battle) and may not need this.
This just says "Hey, use this Id when I'm called." The DialogueContentID is where the actual dialogue is. You usually will want to copy whatever is already in your mission success dialogue and add an opening line about "Coming in to pick-up where you are." or "All targets eliminated. Sit tight, and I can collect you from where you are at right now." and then the rest of the chatter.
Strangely, the default folders for these seem backwards, DialogBucketDef files are inside a "conversationBuckets" folder and the actual conversation dialogue .json inside the "dialogue_buckets" folder.
The Rewards
Flashpoint rewards are listed as a .csv file, or "Comma Separated Values" and if you open the file raw, it would a lot of items separated by commas. However, it's far easier to edit these types of files with an editor like CSVed or others available online. The itemCollection.csv's used for shop inventory and FP rewards have 4 columns:
Here we can see a custom reward table for "The Raid" with the first row, first column giving a title for the .csv table "itemCollection_loot_fp_reward_a_theRaid" and this is what you would type in for the rewards in the MS reward data or in the FP editor main screen as the reward displayed on the title card.
The second row defines a part of a 'Mech, a "mechdef_atlas_AS7-D-HT" and in the third column "1" it defines giving the player 1 of these parts. Take a look at the last two entries, the Gyro and Medium Lasers, you get 4 and 15 of those for this FP. The fourth column, the "weight" or "drop weight" is usually just 1 for a reward listing. For FP's, it will dish out every item on each row of this list in the amount defined in column three.
But what if you want to use a pool of potential items to roll from and give one or two to a player?
Referencing
To use the weighted pool of items, you need to reference another .csv. In rows 3-5 we see "Reference" type entries with a "1" in the third column. This will grant one item from those referenced .csv files.
Calling Other .csv Files
The reference lines must have the Id of the next .csv and lets take a look at the one stock .csv files called in the above reward list. The stock itemCollections are found in:
Opening up "itemCollection_table_Weapon_SLDF.csv" and we only see 2 entries and no weapons. That's because this .csv file we referenced, calls two more .csv files based on RNG. Here, we see the first entry as a fourth column value of "4" and the second entry has "1."
This means the "itemCollection_Weapons_SLDF_uncommon.csv" has a 4/5 chance (80%) of being picked over the "itemCollection_Weapons_SLDF_rare.csv" which has the corresponding 1/5 chance (20%) of getting selected on any one roll. This is how weights work to adjust how common or rare an item or reference can be picked. This isn't out of 100 or any preset total, just add up all the weights in the table and divide you current item by the total to find the odds of it dropping.
Let's say we're feeling lucky and the "itemCollection_Weapons_SLDF_rare.csv" is selected.
Now we see actual weapons. So far, the original reward .csv called for 1 item from "itemCollection_table_Weapon_SLDF.csv" and on that one roll, "itemCollection_Weapons_SLDF_rare.csv" was selected, and now inside that table we will get one roll from the weapons in here. We can see items like the "Weapon_Gauss_Gauss_2-M9" have a weight of just 2 out of a total of 72, or 1/36 (2.78%) which oddly enough is the same as rolling a "12" on two six-sided dice. The other higher weight items like "Weapon_Laser_SmallLaserPulse_1-Maxell" have a 10/72 or 5/36 (13.89%) chance.
Now that you know how to drill through references to other .csv files and how the weights work, take some time to explore around the different possible pools of weapons and gear. You might find some odd stuff in the tables, like the CDA's being in the same rare 'Mech pool as a HGNb in the "itemCollection_Mechs_rare.csv" or other seemingly out of place rewards. If you ever need to find the type of item like "Weapon," "Mech" or "Upgrade" just find them in an existing table.
You would need to determine if your FP needs it's own custom reward list, and if that list would need to reference another custom .csv, or a stock one. These aren't too hard to make, but they can be hard to test, as they are at the end of the FP.
Testing Rewards
I recommend taking my "Sound of Music" FP in the Resources and References above and editing the rewards in the FP file to whatever file you want to test. This FP is just a conversation that you can cancel at any time and then hit the reward screen. This allows for rapid reward testing and you can see what kind of real end results will appear.
One note about the rewards screen - It doesn't show you the amount of the items rewarded in game. So if you see "DHS" on the rewards screen, it looks the same if it's one or a hundred. What I did was setup a "Sound of Music" save just before I accepted the FP but after selling all my gear and anything in storage. Remember, this is using a debug save for testing, so this is fine as long as you are careful. This gives me a clean slate once I'm out of the FP and I can easily see if I got multiples of the same item.
The Original Assets
You might want to create custom images, 'Mechs, Vehicles, cast members, heraldry, Lore descriptions and more. You don't need these, but they can add a special touch to your FP.
In general images should be in the .dds format, and try to keep them as small as possible. The performance modders have advised me to use .dds when possible as it is a lower overhead format for GFX processors compared to .png. However, there are cases where a file must be .png. You can find existing portraits, banners and such in the games files for examples. I'll keep the exact size and more detailed descriptions in the Advanced Editing Post below this one.
CastDef
Creating a new CastDef makes a new name and icon for chat boxes. This does not make a new 3d model of a character in the Argo scenes like Kamea or Yang. This just controls the chat boxes in combat and during Argo conversations. You can however, make a custom portrait for the chat box.
CastDef Portraits Must Be .png Images!
For whatever reason, CastDef portraits are defined by explicit file paths and must be in .png format. This portrait doesn't need to be added to the Version Manifest in ModTek, but you need to keep the file path in mind if you put the version number in your folder structure like "The Raid" does above. When I go to "Flashpoint-The-Raid-1.1.1" from 1.0.1 my file path will break unless I change this before release.
See the advanced FP Editing post below for more details on Art Asset Creation for CastDef Portraits.
Descriptions (Lore Tool-Tips)
This is for the yellow text that you can mouse over in a description or conversation. You can insert these in to a conversation or event like this:
HeraldryDef
The HeraldryDef is what colors and emblems game puts on 'Mechs and Vehicles. The three color ID's work the same as they do in the game's color selection. The colors white and black are named "Greyscale_01" and "Greyscale_05" respectively and the numbers in between are for shades of grey from lighter to dark. The other colors follow a similar progression, with darker colors having higher numbers.
The textureLogoID is not a direct filepath like what is needed for the CastDef. I believe you could add a custom emblem and call it here, as long as it starts with "uixTxrIcon_" and maybe not even that. Can't say I've tried a full custom yet, but I don't doubt it's possible. Keep in mind, only a very narrow selection of skins even shows this emblem. The Shadow Hawk DLC skin is one of those.
MechDef + ChassisDef
I'm not going to cover the basics of custom MechDef and ChassisDef's here, but there are some things you need to know for FPs.
Unit Tag:
"BLACKLISTED"
Make sure your MechDef has this tag added or else it will appear in random procgen contracts outside of your FP or also in Skirmish Mode. Note that this will also prevent the unit's salvage parts from appearing in the salvage pool, so take this in to consideration. It's also a good idea to make your own unique ChassisDef and add the "BLACKLISTED" tag if you really want to make sure the unit does not show up in salvage.
Making a custom enemy is a great way to increase the challenge without adding more units. However, you must keep in mind the difficulty rating of the FP as a whole, what kinds of custom units the player might have at that level and the rest of that mission OPFOR when you're making your custom unit. A simple and generally safe way to make a unit harder is to take the stock 'Mech and just add upgraded weapons in place of the stock components. This is a fast and easy way to add something different without having to create and balance many Lances of custom OPFOR.
PilotDef
The PilotDef controls what Abilities and Traits that unit has access to. You can even set some of the skill levels to 11 or higher and add more Abilities than would be legally available. Check the Mastiff or Kamea files in the stock folder for examples. The PilotDef doesn't have to follow most of the rules around when a pilot should or shouldn't have something. This example is what a full 10 across the board pilot with the "Brawler" (Coolant Vent/Sure Footing) mastery would look like.
Make sure to add the "BLACKLISTED" tag on your pilots! If you don't they'll show up outside your FP in random contracts.
VehicleDef + VehicleChassisDef
Same as MechDef's above, make sure you add the "BLACKLISTED" tag to prevent a custom vehicle from showing up in procgen contracts.
Special note for SRM/LRM Carriers: They don't have turrets and have some bugs that come with it. There are some mods out there like the Vehicle Improvment Project that fix this by adding a turret to the stock vehicle and the associated VehicleChassisDef. If you have a custom SRM/LRM carrier with or without a turret, make your own VehicleChassisDef to match it to prevent mis-matches and failure to load.
The Loading
This is done via ModTek. You will need to use the mod.json format documented here and here. You will need to add any files you want added in to your mod.json manifest. I recommend keeping the same kind of folder structure as HBS in the "BATTLETECH\BattleTech_Data\StreamingAssets\data" folder.
The one exception is .png portraits used for custom castdef.jsons. These are called by direct file paths in the castdef and don't need to be added to the ModTek manifest, they can be, but don't need to. I named my folder "castSprites" to keep it separate from sprites I want loaded in for other things.
The mod.json and folder structure for "The Raid" looks like this:
Each file has a type that can be found in the "VersionManifest.csv" if it isn't listed in the example above. The "Path" is the name of the folder to look for that type of file. Take note at the "Texture2D" line near the end. It has a special addendum "AddToAddendum": "ConversationTexture" as in the VersionManifest.csv there is a specific section called "ConversationTexture" and this is the only way to gracefully add custom images to the Holoscreen. If something isn't loading right, make sure it isn't defined in an addendum specifically.
I'm assuming you built your FP and MS files in a stand-alone folder suggested above. You will need to manually copy them over in to your FP's mod folder, in to their appropriate individual folder each time you save with the editor.
[Mod edit: Reminder. No unapproved links]
The second post will cover advanced topics like spawning requirements, complex Event Results, failure Milestones and contextual conversation options.
One thing I want to say at the start, writing these Flashpoints is a lot of fun. It might take you a while to get it done, but others like @akodoreign manage to put them out incredibly fast. I want to encourage everyone to try and make their own FPs. I've only just got started pioneering the process. I'm sure with more people diving in and experimenting in ways I haven't, we'd be able to tell ever greater stories and expand the experiences possible with BATTLETECH.
Also, I know nothing. I've only been able to hack this all together with experimentation, a lot of help from other modders and asking questions to HBS staff when they had the time to assist on Discord. I'm sure something in here will be wrong or not quite correct, and something I think isn't possible probably is. So, take all this with a grain of salt, I've barely scratched the surface of this beast.
The Idea
First thing is "Why?" Why are you trying to make a FP? Is it to create a challenge? To tell a story? To give players a fun experience? For the challenge of creating something? The reason why you are doing this should be thought about at every stage of the process. Keep this idea in mind as kind of a "mission statement" or anchor that will shape how you form things from the choices the player can make to the kinds of missions you use.
- "I want to make a challenging set of missions based around a planetary invasion"
- "I want to make a few low difficulty FPs for the early game"
- "I want to tell the story about that one time Darius and Sumire got stuck on a frozen world and we had to go rescue them from ice pirates"
Second thing is that Flashpoints are about making a decision. Either A or B, not A & B. Now, you don't need to have a branching choice in your FP, you could just as easily make a full FP with nothing but a single mission and conversation around it, or 4 missions with no conversation or choices. However, the choices you want the players to make, and where those decisions are, will greatly impact the amount of work that needs to be done. Doubly so if you have more than one FP Decision point.
If you make an initial split like "Joint Venture" the missions are on two separate branches for the entire FP. If you make a five mission FP with an initial "A or B" branch, that's ten missions to construct. The earlier the split, or the more splits you make, the more work that needs to be done with missions, conversations, rewards, tag tracking and anything else that makes one branch different than another.
The Tools
Once you have an idea and how the players choices will affect that idea, you can get to work actually building something. HBS has graciously included a set of editors in the game here:
..\BATTLETECH\BattleTech_Data\StreamingAssets\editors
- Flashpoint Editor - For editing FPs and their associated Milestone Sets
- Event Editor - For editing Argo Events like "The Last Cup" or "Happy Accidents" (FFF Burgers)
- Contract Parser - For taking .txt files and converting them in to fully qualified contract .jsons
- Notepad++ - For editing .jsons (a fancy txt file with rules, almost everything in HBS BT is run by .jsons)
- ConverseTek - For creating custom conversations on the Argo with your crew.
- CSVed - For editing .csv files used in itemCollections for FP rewards.
Debug Mode
You're going to want to enable Debug Mode to allow quick turnaround for testing. A Debug Save populates all available FPs within 14-30 days and lets them re-populate quickly if failed. Be aware, don't leave this on all the time. It generates some default dump files and will mess with your PvP sync if the other end doesn't have it enabled too.
@HBS_Eck has created Eck's Debug Guide for modders.
What can Debug Mode get you?
simgame Debug Window
You can spawn 'Mechs whole, grant cash and rep/MRB ratings and more. You can't access this window in a non-Debug save.
combatgame Debug Window
You can enable "God Mode," auto-win a contract, dump info and more. This can be accessed in either Debug or non-Debug saves.
Over the course of figuring out how to make an FP, I've come back to a lot of lists, charts and other references over and over again. I've compiled the stuff I needed to reference together in to one googledoc. This contains a lot of data pulled directly from the game's MetaData Database (MDDB) and other sources. Huge shout out to @scJazz who compiled the immensely useful "Contracts" sheet for me with the optional chunks listed. That saved a lot of time narrowing down which contracts I could build from quickly.
Flashpoint Reference Sheets - GoogleDoc
Flashpoint Stock Photos is a small mod with some very basic Holoscreen images like the missing "Locals Liaison" and a map of the Inner Sphere that are not present in the base game. I made this streamlined image pack to allow FP authors to share some basic imagery without needing to duplicate it for each FP.
Flashpoint Aid: FP_choice_placeholder.bytes
FP_choice_placeholder.zip attached in this post contains a single .bytes conversation file. This file is nothing more than a simple conversation with the common Flashpoint Decision Tags clearly displayed. It is used as a placeholder for your FP's TalkChoice conversation until you have written your own. This allows you to test out the FP's Milestone linkages and tags quickly. You can also open this in ConverseTek and edit the tags or node as needed for testing.
Flashpoint Aid: "The Sound of Music"
"The Sound of Music" is a Flashpoint I created to just listen to each possible music track you can call for Argo conversations.
Flashpoint Aid: "Training Wheels"
"Training Wheels" was my initial proof of concept that a custom FP could be done. I'll re-work this in to a proper guide/FP in time.
Flashpoint Aid: "The Raid"
"The Raid" is my first fully featured FP and touches nearly every aspect of the game, from custom missions and OPFOR, to failure branches and post FP events. This can serve as a comprehensive working reference for about anything that needs to be done.
Writing Aid: Classic Battletech Style Guide (Archived)
This archived page contained the writers guide for BattleCorps story submissions. This is an excellent source for how you should write BT specific words like 'Mech, MechWarrior, DropShips, ranks like Tai-sa and units like the Twenty-first Galedon Regulars in the correct format.
Eck's Contract Parser Guide
@HBS_Eck has also put together a Contract Parser Guide to the Contract Parser I will cover below. This tool that comes with the game will allow you to quickly put together the custom contracts for your FP.
Flashpoint Reference Sheets - GoogleDoc
- Map Names - List of all maps by Biome
- MoodIDs (Weather) - List of all weather types, "Verdant" set is used for High/Lowlands
- EncounterLayer (Map+Contract) - List of all possible combinations of Map+Contact type sorted by contract type
- Contracts - Listing of contract .json names and what kind of optional chunks they have active by default
- CastID/SpeakerID for Group Conversation - List of likely cast members for Argo conversations, not every castDef is listed, just those used in the stock game in an Argo conversation
- uixTxrConv for Viewscreen Image - The list of images that can be shown on the Holoscreen, the "uixTxrConv_" prefix has been removed for easy copy/paste in to ConverseTek
- Commander Tags - Your Commanders history choices like "Taurian Ancestry" or "Exiled"
- 'Mech Lance Tags - Used in procedurally generated Lances, so you can get an idea of what could spawn
- Color Swatches - For custom Heraldry, these are the same color options for your 'Mechs paint-job
Flashpoint Stock Photos is a small mod with some very basic Holoscreen images like the missing "Locals Liaison" and a map of the Inner Sphere that are not present in the base game. I made this streamlined image pack to allow FP authors to share some basic imagery without needing to duplicate it for each FP.
Flashpoint Aid: FP_choice_placeholder.bytes
FP_choice_placeholder.zip attached in this post contains a single .bytes conversation file. This file is nothing more than a simple conversation with the common Flashpoint Decision Tags clearly displayed. It is used as a placeholder for your FP's TalkChoice conversation until you have written your own. This allows you to test out the FP's Milestone linkages and tags quickly. You can also open this in ConverseTek and edit the tags or node as needed for testing.
Flashpoint Aid: "The Sound of Music"
"The Sound of Music" is a Flashpoint I created to just listen to each possible music track you can call for Argo conversations.
Flashpoint Aid: "Training Wheels"
"Training Wheels" was my initial proof of concept that a custom FP could be done. I'll re-work this in to a proper guide/FP in time.
Flashpoint Aid: "The Raid"
"The Raid" is my first fully featured FP and touches nearly every aspect of the game, from custom missions and OPFOR, to failure branches and post FP events. This can serve as a comprehensive working reference for about anything that needs to be done.
Writing Aid: Classic Battletech Style Guide (Archived)
This archived page contained the writers guide for BattleCorps story submissions. This is an excellent source for how you should write BT specific words like 'Mech, MechWarrior, DropShips, ranks like Tai-sa and units like the Twenty-first Galedon Regulars in the correct format.
Eck's Contract Parser Guide
@HBS_Eck has also put together a Contract Parser Guide to the Contract Parser I will cover below. This tool that comes with the game will allow you to quickly put together the custom contracts for your FP.
The Workflow
"This is a lot of crap! Where do I start?" is something you might be asking. I find it's best to create the Flashpoint file in the editor, formulate your FP structure and branching, test that format with placeholder conversations, missions and rewards and then fill in the rest as you wish. Getting a solid FP structure and testing them out to make sure you can go from one link in the chain to the next is essential and should be robustly stress tested to make sure you won't leave a player stranded with a bad conversation, tag or branch that goes nowhere. It's really easy to make a FP that links to a bad/missing item and enter a shadow-zone where Farah or some other crewmate has gone invisible and you can't complete or abandon the FP to get them back. I've done it many times...
The Templates
HBS has included a bundle of templates for just about everything in the game, including FPs. These are the same templates the stock FPs are built from and their conversation filenames still reference the type they were built from. These templates are great examples for almost any combination of FP branches from early/mid/late splits, optional objectives and even three-way splits. You can also use a modders FP files as working examples. The stock FPs are kept inside an asset bundle, away from easy access. They can be extracted and referenced, but I'm not going to discuss that in this post. The default templates are located here:
The Flashpoint Editor will look for .json files in this location by default and save files there as well...\BATTLETECH\BattleTech_Data\StreamingAssets\data\flashpoints
THIS IS NOT WHERE YOUR FP NEEDS TO BE TO LOAD IN TO THE GAME.
I'll address this down in the ModTek section below.
The Stand-Alone Editor Folder
While this is an optional step, I highly recommend doing this before you start editing anything.
There's a really big chance you might insert something in to the stock folders or edit something you shouldn't have if you work out of the game's running \StreamingAssets\data\ structure. However, the various editors assume this structure and pull items from it. What I did was copy everything I needed out of the game's folders. This also ensures any HBS update or steam/GoG/etc validation doesn't remove your files.
Before you copy these HBS folders out of the \BATTLETECH\BattleTech_Data\StreamingAssets\ you need to make sure you copy the folders inside \data\ without the "assetbundle" or "maps" folder, these are massive and you don't need them. Removing them cuts the Stand-Alone Editors to about 150mb from many gigs in size.
Afterwards, I made a desktop shortcut for the FP editor at the new location. This makes it easy to use in the isolated location and my actual game files stay unaltered even when I make mistakes at 3am. You do need to make sure you copy over all of these again anytime HBS pushes an update.
The Flashpoint .json Structure
The Flashpoint Editor opens a FP file, "fp_TEMPLATE_initialChoice.json" from the location above. This file contains:
- The displayed name, InternalName and Id of the FP as a whole ("Joint Venture" is displayed, "longRoad" is the InternalName and fp_longRoad is the Id)
- Icon - The image at the top of the title card, all stock FPs use a blank entry for the default FP banner - Must be .png or .dds, default size is 750x300 pixels
- Weight - The odds this FP spawns next, default is 10, Joint Venture is 200, Alliance FPs are 1000
- Difficulty - 1-10, this is 2x the skull values you see in game. Diff. 10 = 5 Skulls, Diff. 5 = 2.5 Skulls
- Required or Excluded Tags - Like requiring "ALLIED_FACTION_Liao" for the Liao Alliance FP
- Location Requirements - What planet(s) it takes place on, usually the tag of the planet itself "planet_name_adrar"
- PotentialEmployers - Who's paying for this mission
- TargetFaction - Who the Employer is paying you to hit
- Optional Restrictions - Min/Max Drop weight warnings, no refit time, etc
- MilestoneSetID - This tells the game what Milestone Set to use, the most line of code in your FP
- RewardCollectionID - The default reward and title card reward description
- FlashpointShortDescription - The short description seen at the bottom of the title card
- FlashpointDescriberCastDefId - Who is telling the player about this FP
In the FP editor it looks like this:
Editing FP Files
HBS Formatting for FP files:
- Filename: fp_yourStory.json - Created by saving the FP after setting InternalName
- Id: fp_yourStory - Created by setting the InternalName
- InternalName: yourStory - The first word is often not capitalized in HBS-Land, consider it a general rule
- Name: Your Story Title - What you want the title card, and thus the player to see as the title for this FP
Changing your internal name has cascading effects on the resulting files created and associated with this FP. The first step in editing your FP should be giving it a unique internal name you don't intend to change. Remember, this isn't the name shown to the player, ever. This is just the name the game uses to categorize your stuff from another FP.
Set the Location Requirements (Employer, Target and Planet)
The next thing you would want to define is who is this FP fighting for, against and what planet it starts on. The section labeled "Location Requirements" shows the "Potential Employers" which can be edited and selected from the list of faction tags. I've not experimented with multiple potentials yet.
The Target Faction is a drop-down list, take note of the spelling and capitalization of factions on this list. You will need to copy these exactly as shown for later when you define your contracts in milestones.
The "Required Tags" is where you would define what planet it starts on. I believe it might be possible to start a FP at one location and move to others, but I haven't tested this. You can find the tag you need by opening up the data/starsystem folder and opening the planet's .json file you need. You will see a tag with the planet's name on it:
This would set the possible starting planet to require the tag "planet_name_Tiverton" of which only one planet has, Tiverton. I picked Tiverton for "The Raid" because it fit my needs the best. The story dealt with assaulting the Black Market on an independent world and I had certain Biomes in mind. I had to look around in-game in one of my saves with Black Market access and looked for the one or two that fit my needs best. I recommend doing this in a Debug save, to see if any FPs already appear on that world. You will also need to pay attention to the Biomes that world supports, found in that planet's .json. You don't really want a Martian or Lunar only FP taking place on worlds that don't have that available. However, I did manage to set my first two missions on a Lunar Biome, even though the Tiverton.json did not have that in the list of supported Biomes that generated contracts would select from. I also made sure to write in why I was using a normally unsupported Biome for that planet. In my case, one of Tiverton's moons was being used for a Black Market exchange and officially the moons had never been colonized.planet_name_Tiverton
Set the Optional Restrictions
This can be done near the end of your process. You might want to check some of them right away, but I don't think the game or the editor cares too much if what is selected is accurate. You could check "Allow Refit" and then make a FP with all consecutive drops with no refit pause in between. Make sure your final product is accurately reflected in your optional restrictions.
Set the Short Description
This is the text at the bottom of the title card. This is should be short and sweet and try to entice the player in to accepting your job. Like the optional restrictions, this can be saved for later to make sure it accurately reflects the final product. You may want to look at other stock title cards to get an idea of what info they deemed important, sometimes less is more.
Setting Conditional Requirements for FP Spawning
You can set FPs to only appear if the player's save has or doesn't have certain tags or values like "MRB Rating greater than X" or must have/not have "ALLIED_FACTION_Liao" and I'll cover that in the Advanced Editing Post below this one. For now, it's better to just get your FP structure laid out and tested before adding restrictions on it appearing.
Setting the Icon
A picture can say a thousand words and HBS made one title card icon to represent all FPs from Joint Venture to ones featuring Morgan Kell and Justin Allard. You don't need to make a custom icon for every FP. I'm going to recommend it though. This will help clearly separate stock FPs from modded ones even if a player has left the game for months and comes back to it, forgetting what was stock and what was modded, then makes a bug report about a non-stock FP.
The format for title card icons are:
- .dds or .png files
- 750x300
- Flipped on the vertical axis for both formats
- Filename prefixed by "uixTxrSpot_"
Note the dark bar at the "bottom" of the image, this is to make the "Flashpoint: Expires in X Days" stand out against a similarly colored background, this bar is 24px tall and I think the in-game bar is roughly 24 or 25px high. There is also a light blue "Active Flashpoint" bar that replaces the expiration date once you accept the job, so I recommend a darkened or full black bar so any status message pops out and is easily readable.
The Milestone Sets Structure
The Milestone Sets (MS) are the most important part of the FP. If the FP file is the "cover" of a choose-your-own-adventure book, the MS .json is the index and the breadcrumbs at the bottom of the pages. The MS file such as "ms_fp_TEMPLATE_initialChoice.json" contains all of the triggers, event results, branches and mission parameters for the FP.
The MS file is created by the FP Editor alongside your FP file when you save it for the first time. As it's created by the Editor for you, it takes care of a lot of the naming and formatting. The "Reorder Milestones by Links" will format them automatically. MS files are .jsons stored in and read from:
Be aware, the "milestones" and "milestoneSets" folders are different. "milestones" is used for the main campaign and each milestone was a separate .json, where milestoneSets are collections of milestones all inside a single .json for FPs. This is a much neater system and some of the functions are not the same between the two...\BATTLETECH\BattleTech_Data\StreamingAssets\data\milestoneSets
In general, MS start a 001 and increment up until they branch out. Each branch increments the first digit by one. In the initialChoice template, where the branch is at the start, we see this:
- ms_fp_TEMPLATE_initialChoice_001_Start
- ms_fp_TEMPLATE_initialChoice_002_TalkChoice
- ms_fp_TEMPLATE_initialChoice_003_Branch
- ms_fp_TEMPLATE_initialChoice_100_A-Mission
- ...
- ms_fp_TEMPLATE_initialChoice_103_A-Complete
- ms_fp_TEMPLATE_initialChoice_104_A-Reward
- ms_fp_TEMPLATE_initialChoice_200_B-Mission
- ...
- ms_fp_TEMPLATE_initialChoice_203_B-Complete
- ms_fp_TEMPLATE_initialChoice_204_B-Reward
- ms_fp_TEMPLATE_initialChoice_300_Cancel-Complete
- ms_fp_TEMPLATE_initialChoice_301_Cancel-Reward
At this point, the best thing you can do is to open up the FP Editor, pick a template like "Initial Split" and browse through every MS by clicking on one to highlight and then hit "Edit" to see more details. Going through these first, then looking up how each data field is used will help you put it together better than reading this guide strait through.
This initialChoice template would have us start, go in to a "TalkChoice" MS where it would call a conversation, have us pick a Flashpoint Decision inside that conversation and set a unique tag. Then, the Branch MS would trigger and pick one result that matches the tag applied in the conversation, sending us on either the 100, 200 or 300 branches. The 100 and 200 branches have missions, talks and other MS labeled "A" and "B" respectively. You can have a "C" branch, and maybe even more, but the workload starts to become cumbersome.
Inside each MS, there is an "Action" that must contain a link to the next one in the chain. You can have multiple actions in a branching MS that link to different MS but make sure your use of Required/Excluded tags is logical sound and won't allow double dipping. The three kinds of actions that can set a next milestone link are:
- Flashpoint_SetNextMilestone - Just type in the next MS id in the data here
- Flashpoint_AddContract - Has the line "Next Milestone Id" works the same as "SetNextMilestone"
- Flashpoint_StartContract - Has the line "Next Milestone Id" works the same as "SetNextMilestone"
You should edit and create MS inside the FP editor, but you can copy/paste and edit MS whole or in part in the .json with a text editor. So far, I create the MS and names in the editor, click "Reorder MS By Links" and then save the FP and exit the editor. I then open the ms_fp_yourStory.json in Notepad++ and correct the rewards MS numbers as they are bugged and get re-numbered. If you don't like the default numbering scheme, you can change that manually too, but be careful. Once that's edited, I re-open the FP editor and click Reorder again, if the only errors look like this:
Code:
ERROR-Milestone with old id [ms_fp_theRaid_108_HalfCredit-Reward] and new index[800] doesn't have anyone who points to it.
Code:
ERROR-Milestone with old id [ms_fp_theRaid_002_TalkForCancel] and new index[2] has a next milestone id [ms_fp_theRaid_003_BranchForCancel1] which could not be found.
ERROR-Milestone with old id [ms_fp_theRaid_003_BranchForCancel] and new index[100] doesn't have anyone who points to it.
ERROR-Milestone with old id [ms_fp_theRaid_100_MissionSim] and new index[101] doesn't have anyone who points to it.
NOTE: BUG FIXED IGNORE THIS -There is a bug with the Reorder Links Button, it doesn't recognize "Rewards" MS that come after "Complete" MS and you can just hand edit them back to 100/200 series as needed using your .json editor.
Here is the pop-out Milestone Editor Form, opened by clicking "Edit" after highlighting one of them in the MS list at the bottom of the FP editor. The Id and Name are somewhat hard to edit and grasp at first. Changing the name, then hitting the "Reorder Milestones By Links" in the main FP editor window will update the Id to "ms_(FP Id)_(Number)_(Name of Milestone)"
The "Scope" of these is usually "Flashpoint" to tell the game it takes place in the realm of this specific FP. The Scopes cover the areas you'd expect in that the "Company" scope covers the kinds of things like tags you take with you after events or completing the Campaign or FPs. The "Mech" or "Mechwarrior" Scopes would get used in Argo Events to wound or impact a specific pilot or 'Mech. For FPs, the two scopes that are the most used will be "Company" and "Flashpoint." At first, just keep these to what the templates use, which is usually "Flashpoint" for the MS Editor Form.
Towards the bottom of the MS Editor Form, there is a list of "Results," these are the core of what happens during this MS and where to link to the next MS in the chain. The titles of these events are declared in their "Scope" in the MS Event Results Screen.
- Company - Almost all of your Event Results (missions, convos, complete, rewards) will be Company Scope
- Flashpoint - Your starting MS will have one of these to clear any FP choice tags at the start, also possibly to set a choice tag in a later MS
Keep in mind, Company Scope tags and status modification edits like Mech/MedTech numbers will carry on after the FP is completed or abandoned. If you are not careful to set some of these things as temporary, you can permanently alter the players Argo Tech crew counts, morale, cash and even make cast members go invisible forever. Use these carefully and try to test them thoroughly to make sure anything you alter can be undone in a reasonable time.
The MS Event Results Screen
This is what you see when you hit Add/Edit a MS result. In this case, there are two things this Event Result does:
- Flashpoint_AddContract-mapGeneral_tropicalCove_vJung
- System_ForceDropshipRoom-Contract
First, at the top, there is the Scope of this Event Result, "Company" in this case, no tags are added or removed and just below we see the "Random Scope" area. This is a LIE. This area is a "Required Scope" area, not "Random." This is where you would check for if the player has/has not certain tags or comparisons such as "Morale Greater Than X." This area is where your FP Branch MS detects which fp_choice_x tag the player has been given and where to go from there. This is an incredibly important thing to pay attention to and below I will show you how the branching works.
Within this Company Scope Event Result, the first Action sets up the details of the currently available contract. You can see the details of it on the lower right. There are two different Actions that generate a FP contract.
- Flashpoint_AddContract - Creates a non-consecutive Contract, like a normal job
- Flashpoint_StartContract - Forces a consecutive Contract to start immediately
A "Flashpoint_StartContract" does not need a "System_ForceDropshipRoom" Action as it's implied and does that for you.
If you are going any kind of drop restrictions (Min/Max Tonnage by unit or Lance), I'd recommend you not drop them on a player as "Flashpoint_StartContract" or else they may be forced in to a DropShip Equip screen they can't exit, with no valid units to select and can get stuck. You can still do this, but make sure they are very well informed before entering a mission chain they can't back out of.
Currently, I don't believe it is possible to safely set a "Flashpoint_AddContract" that is also on a kind of timer that would force-start it once the timer expires. I tried this for "The Raid" and asked the devs if this was possible, but while it might be, it's an incredibly risky implementation of tags, events and other parts that shouldn't be used in such a way as it risks harming the save. The devs did not recommend I use it and I agreed.
Flashpoint_AddContract/StartContract Data
The Flashpoint_AddContract sets up a lot of essential items for the contract it generates. It however, is not the entire contract. First and foremost, it must point to a contract .json file in the "Contract Name" entry. You can just use a default contract found in the \data\contracts\ folder as a placeholder. I made sure to pick some very low difficulty ones from the FP Reference Sheet that had the right type of contract (Assassinate, Convoy Assault, etc) So I could get an idea of how the FP flow and branching works before I take the time to customize the contracts.
Next most important thing is going to be the map this takes place on with "Map Name" and "Encounter Guid" defining what map, and which part of that map to use. This is where the spawn points, buildings, convoy routes and other map layer stuff gets selected. I can have a contract.json that is a "simpleBattle" but that .json cares not what map it is applied to. You can give it a valid "Map Name" and if available, an "Encounter Guid" to apply that contract.json to. If you leave both of them blank, the game will use a fallback default map every time. Use my FP Reference googleDoc's "Encounter Layer" sheet in the "References and Resources" tab to pick from the possible combinations of map + encounter type. You will see some "simpleBattle" encounters have up to 4 different possibilities on a single map. If you want to use one of those that isn't the default or first entry, paste that EncounterLayerGUID in to the "Encounter Guid" section of the Flashpoint_AddContract Data, along with the corresponding Map Name.
Now that you have a contract.json and the map+encounterLayer it takes place on, you can copy/paste the Employer and Target Factions from the main FP screen. Spelling, spaces (none) and capitalization are critical here, I highly recommend a strait copy/paste and make sure no leading or trailing spaces get inserted. You can have these be different than the base FP's factions, but be careful. This would be used for you betraying your employer for the enemy, or hitting your own target, that kind of thing.
Optionally, if your contract has a special Employer's/Target's Ally Lance appearing (by default only some Target Acquisition contracts can do Enemy Allies) you set that here too. However, I ran in to a number of bugs getting this to "stick" on to the contract and to be sure, doubled up that info where it was present in the contract.json for that mission.
The Difficulty is out of 1-to-10, with 1 = 0.5 Skull and 10 = 5 Skull contracts in-game. This overrides the base difficulty setting in the contract.json, as they are only formatted as Easy/Med/Hard (2/5/8) and I'll address that later in the Contracts section. Normally, this difficulty will be the same as what you declared your FP to be and the game will scale the payments as appropriate. This difficulty is what the pay rate for the contract is built from in addition to the type of contract!
Next Milestone ID is exactly what you think it is. It defines which MS to link to next, if the mission is a success.
Failure Milestone ID is the same, but for when you fail the primary objectives or withdraw from the mission. I'll discuss this in more detail in the next post below.
Conversation MS
So that covers a mission, the map it takes place on, and where to go in the MS links once completed. But what does a conversation MS look like?
This is the ms_fp_theRaid_104_TalkChoice Event Result. It has two Actions:
- System_StartConversation - Starts a conversation with a title card defined here
- Flashpoint_SetNextMilestone - Sets the next MS link in the chain once the conversation is done
You will need to open the ms_fp_yourStory.json and hand enter the convo GUID in to the space provided!
Code:
"Actions" : [
{
"Type" : "System_StartConversation",
"value" : "9cc52ed03b2514c7432b5978",
"valueConstant" : null,
"additionalValues" : [
"The Raid",
"High Orbit \u2014 Tiverton",
"Conference",
null
]
},
{
"Type" : "Flashpoint_SetNextMilestone",
"value" : "ms_fp_theRaid_003_BranchForCancel",
"valueConstant" : null,
"additionalValues" : null
}
],
In The Conversation segment below, I'll show how the FP Aid: FP_choice_placeholder.bytes can be used as a placeholder until your proper conversion is written.
Branch MS
The Branch Milestone is a kind of filter. It will check for some default tags like "fp_choice_a" or "fp_choice_b" and have different Event Results for each. Here is the Event Result in the Branch MS for "The Raid" that sets you down the A branch.
Take a look at the top, it has a Scope of "Company" and a Random Scope (really "Required Scope" and "random" is an error) of "Flashpoint" with a Requirement of "fp_choice_a" in the Required Scope. This means, to get to this Company Event Result, the Flashpoint Scope must contain a tag of "fp_choice_a" and that's how you start down this FP's "200_A" branch. In the previous conversation, it is possible to pick up either "fp_choice_a" or "fp_choice_b" or pick up none of them at all. I used this "no tag applied" setup for an early exit, allowing the player to take the A or B branch as an optional objective.
Here is that early exit MS Event Result, same Company Scope and FP Required Scope as the one above. However, the requirements are in Excluded Tags, which means you "must not have either fp_choice_a or fp_choice_b" in your FP Scope to get here. I could have also used a Requirement Tag of "fp_choice_c" instead, but when I built this, I didn't need to add a third tag. In the end, I did need one for some advanced conversation filtering, but that's for later in the advanced editing post.
The templates usually include this cancel path, but honestly, I don't think most FP's need one. You're really going to be pushing the player to complete the FP. Once you get in a few missions, offering them an out is kind of a red herring. If they fail/abandon it, it goes back in to the pool to try again. If you have a "Cancel Complete" it will "Finish" the FP once and for all. If you only want to give the player one shot at something, this is where to use it. Use "one shots" sparingly, probably for a great reward like a AS7-D-HT or a pair of Gauss Rifles and ammo.
Complete and Reward MS
Once it's all said and done, Darius usually puts everyone back to work and now you hit the completion Milestone and your reward. At the top, you will usually set some Company Scope tags to signal this company has completed this FP and took a specific branch.
The aptly named "Flashpoint_CompleteFlashpoint" declares it over. Here you set the final "Reward" MS to point to and then if you want to override the default reward you set in the FP json on the main FP editor options. In this case, the A branch gives more payout than the base and I overrode that to point at my A branch reward .csv file. If the default reward is what you want, leave the override blank.
If this is a "Cancel Complete" the "FP End Type" would be "CompletedWithoutReward" otherwise it seems to be left blank by default.
The "System_ForceDropshipRoom" to "Ship" just sets the menu back to the main Argo screen once we are done with the reward issue.
The Rewards MS does not set any loot rewards!
Those are defined in whatever .csv file you pointed the FP or Rewards Override to.
What the Rewards MS does set is any non-loot items like C-Bills, Morale, Reputation changes and other "status" type numbers. These are in a specific format, the same kind of format the Event Editor uses and if you need one for reference, you can check stock events that modify that value in either the .json or in the Event Editor. This reward shown has:
- Funds|System.Int32|3900000
- Reputation.AuriganPirates|System.Int32|-30
- Morale|System.Int32|1
- BlackMarketAccess_Display|System.Int32|-1
It pays out 3,900,000 C-Bills, lowers your Rep with the AuriganPirates by 30 (this is in addition to the Rep loss from contracts taken in the FP), adds +1 Morale and sets the "Black Market Access Display" to -1 or off. This FP dealt with raiding the Black Market and once you finish it, they are quite pissed and this is part of the steps needed to remove the players access. Note, in the background in the MS Editor Form, there is a second Event Result that is (Temp), this one sets the temporary time for the Market to not show back up. If you look at the top, you will see a list of tags added and removed. These deal with Black Market, mainly shutting it off and once it can come back on, giving the players company a "BANNED" status to let only the most expensive offer give them renewed access. It was worth it, or at least I think so. Main thing is, everything this FP does with the BM is actually temporary. It might take 666 days before you are available to get the "Banned offer" to restore access, but I'm not permanently cutting a save off from what is a pretty big feature in the simgame.
I'll cover Temporary Event Results in the Advanced Editing portion below. What you have above is the heart of the FP system. You have a set of Milestones linked together with a branching path of conversations, missions and finally the rewards. That's how you assemble a basic Flashpoint in to a playable state.
The Conversations
The main page of CWolf's ConverseTek (CT)has a general use guide and for FP's your conversations are going to take place in the "Conference" room as set by the "Talk" MS that calls it. Most of what goes in the conversation is the same as the CT usage guides and videos on CWolf's page. I'd recommend calling cast member by "CastID" over the harder to read "SpeakerID" and have made a chart of the common ones in the CastID/SpeakerID for Group Conversation of the FP References Sheet in the Resources and References tab. This isn't a comprehensive list, just what already appears in the stock game. You can type in any other castID and it will appear in the chat box just fine and it will show their Name/Title and portrait as defined in the castdef.
Setting a Holoscreen Image
Adding the Action "Set Battletech Viewscreen Image" and enter the filename of the image you want without the "uixTxrConv_" prefix in front. The sheet after the CastID/SpeakerID is a list of all the stock images you can call. You can add custom Holoscreen images and I will cover that in "Original Assets" below.
There is no stock way to "clear" the Holoscreen without error that I am aware of. If you call a image it can't find, it will display a clear screen. I don't like this method and so made a "screenoff" empty image file as part of the Flashpoint Aid: "Flashpoint Stock Photos" mod that I highly recommend using for your FP.
The custom castdef, Holoscreen image and the instructions on the CT git for contextual responses will get you here:
NOTE: Once you use a "Lock Camera" Action, you must manually assign any further camera changes in the scene. I don't know if it's possible to return the camera to "Normal" mode in CT at this time.
Setting a Flashpoint Decision Response
The big thing unique to conversations in FPs is the Decision Choice that takes place somewhere in the FP. These are responses as such:
Code:
<color=#85DBF6FF>[Flashpoint Decision: Make a choice]</color> I'm making this choice.
ConverseTek Action: Apply a Flashpoint ScopeTag
Give a Node or Response an "Action" select, "Set BattleTech Tag"
Action:
Operation: Get Preset Value (int)
Key:
Type:Key:
string: SimGameAddRemove
Value:Int: 0 (Add to)
Operation: Get Preset Value (int)
Key:
Tag Key:Key:
string: SimGameScope
Value:Int: 3 (Flashpoint)
string: fp_choice_a
This is basically saying "Add to SimGameScope: "Flashpoint" the tag string: "fp_choice_a" and this is usually done to a Node in HBS's examples. It can be applied to a response as well and should work.
To make this easy for everyone, I've made a placeholder conversation, check the Resources and References segment above for Flashpoint Aid: FP_choice_placeholder.bytes which is in a .zip file at the end of this post.
All you need to do is D/L this file, paste it's GUID "9caaf9ff484fe7d2823c5d7e" in to your TalkChoce MS Conversation value and you should have a working conversation that can apply the tags needed for most default Branch MS.
The Contracts
The contract .jsons can be edited to make custom missions within their general type. A "SimpleBattle" isn't going to become a mutated "Defend Base" no matter what kind of cut/paste hack job you do in the .json. This is an incredibly limiting factor at this time and I don't know if it can be bypassed yet.
This is because the contract .json is a map agnostic file. It specifies an existing contract type (SimpleBattle, Rescue, Destroy Base, etc) and that calls a specific EncounterLayer for the map selected. This layer is part of the map files and includes the coordinates for spawning locations, patrol routes for AI and everything else needed to run that type of contract on that specific map. Currently, we don't have an easy way to edit and create EncounterLayers and associated files, Mission Control by CWolf is very close to becoming this tool.
So how do we go about customizing the missions we have? First, you need to figure out which type of contract you want to build from. Then, I'd recommend selecting a map. You need to make sure the map you want had the appropriate EncounterLayer for the contract type. You can check the EncounterLayer (Map+Contract) of the FP References Sheet in the Resources and References tab to check maps sorted by contract type. I'm usually searching for a specific Biome (Lunar, Tropical, Highlands, etc) and make a list of maps available in that contract. Watch out, some maps or Biomes only have one possible setup. A Lunar Rescue for example only has one map available, but a Lunar Destroy Base has two. Still, that's only two possible Lunar maps where Tundra has four. Remember, some maps+contracts have up to 4 different EncounterLayers on a single map and they can all take place on drastically different terrain layouts even if they are on the same Biome and larger map space. The EncounterLayerGUID can be pasted in to the Action Data if it's not the first default entry for that map to use the other layers.
The next biggest thing we can customize are Optional Chunks. Some Defend Base contracts have APCs that turn on turrets, most don't, some Battles have a second Lance, others are just four units. These can be turned on and off by setting their Optional Chunk to "true" or "false" and what contracts have what chunks turned on or off can be found in Contracts of the FP References Sheet in the Resources and References tab above.
As a placeholder, you can find the stock contract that has all or most of the optional chunks you need turned on and then place that in your Mission MS and along with a map. You might have to go through a number of maps until you find one you like as enemy spawns, extraction zones and of course the terrain itself greatly changes how easy or hard that contract will be. A "SimpleBattle" with two far off Lances at the players 2&10 o'clock a mountain in between them is going to be handled much easier than the same two Lances spawning at 12&6 with no intervening terrain or cover at player spawn.
Now you have a general idea of how a mission will play out and maybe narrowed down the possible maps to 2-4 candidates. You can either take a stock contract .json and edit it, or build your own from scratch using the Contract Parser Tool in the edtitors folder alongside the FP editor. I'll cover editing the .json directly below the parser, but recommend using the parser first.
Contract Parser
The Parser takes a template .txt file and turns it in to a fully qualified contract .json for you. I recommend this method for all contracts except "FireMissions" (Target Acquisition) as the parser we have doesn't handle them at this time. HBS included all the stock contracts and stock template .txt files for us here:
The Parser can be found in the editors folder and is called "ContractParser.exe" but opening it will do nothing, it needs to be run via .bat file. You will see some .bat files in the folder, but they will not work out of the box. You must edit these files in Notepad++ and change the file destination away from the dev. file addresses they come with by default. I recommend saving your edited .bat files under a new name so game updates or a copy/paste dump for your Stand-Alone Editor Folder won't overwrite them by accident.BATTLETECH\BattleTech_Data\StreamingAssets\design\contracts
@HBS_Eck made this Contract Parser Guide that goes in to far more detail about the specifics of the contracts.
Here is a copy of one of my .bat files, with the file path changed to reflect my person Stand-Alone Folder:
Code:
REM In the built game, change StreamingAssetsSource to just StreamingAssets
contractparser "..\..\Editor Stand Alone Folder\design\contracts"
Code:
REM In the built game, change StreamingAssetsSource to just StreamingAssets
contractparser "..\..\Editor Stand Alone Folder\design\contracts\amechcustoms"
This makes it easy to find my output and not regenerate a ton of stock contracts every time I need to run it. On the first you will get at least 1 warning, that it needed to create a custom output folder as "amechcustoms" or "yourfoldernamehere" will not exist in the data\contracts folder already. Here we see two random design\contract files I put in to my custom design\contracts\amechcustoms folder and they pop out as valid game ready .jsons on the right inside my Editor Stand Alone Folder\data\contracts\amechcustoms folder created by the parser's first run above.
For the next three sections I'm going to notate these for both the .json and .txt templates using the DefendBase_BreakthroughBrink.json, DefendBase_BreakthroughBrink.txt and DefendBase_Template.txt as an example except when special FP options are needed.
Editing Contracts for Flashpoints
At the top of all the files we got our basics, ID, Name and Difficulty. FP contracts ID and Naming Conventions:
For a first mission, no branching yet:
- ID: "c_fp_yourStory_1_defendBase - prefix c_fp_yourStory_(mission #)_contractType"
- contractName: "Your Story" - Displayed to user, FP Displayed Title with no Mission # in Roman Numerals
- ID: "c_fp_yourStory_a1_defendBase - prefix c_fp_yourStory_(branch)(mission # in branch)_contractType"
- contractName: "Your Story IV" - Displayed to user, FP Displayed Title and Mission # by total missions played
Code:
"difficulty" : 8, or [Difficulty]Hard
&
"longDescription" or [LongDesc]
Oddly, these are flipped. The Short Description is the paragraph in the negotiation and loading window. The Long Description is the one or two liner that Darius usually gives you underneath the full description.
Code:
"shortDescription" : "A {TEAM_EMP.FactionDef.Demonym} industrial lab is at a critical juncture in its R&D program. Any disruption would set us back a decade. {TEAM_TAR.FactionDef.Name} on {TGT_SYSTEM.name} has discovered this, and they've already interdicted the first lance of 'Mechs that were sent to defend the facility. We need mercenaries to step in and buy the time necessary for further reinforcements to arrive.",
"longDescription" : "I'm guessing our employers know that a hammer blow is coming, so we'll expected to take the brunt of the attack until their reinforcements arrive on the field.",
[ShortDesc]A {TEAM_EMP.FactionDef.Demonym} industrial lab is at a critical juncture in its R&D program. Any disruption would set us back a decade. {TEAM_TAR.FactionDef.Name} on {TGT_SYSTEM.name} has discovered this, and they've already interdicted the first lance of 'Mechs that were sent to defend the facility. We need mercenaries to step in and buy the time necessary for further reinforcements to arrive.
[LongDesc]I'm guessing our employers know that a hammer blow is coming, so we'll expected to take the brunt of the attack until their reinforcements arrive on the field.
"salvagePotential" or [Salvage]
This must be a multiple of four! I also don't think a value higher than 28 is found in the game. The game also doesn't let players pick priority salvage over 7 (7/28?) and if they have "Generous Salvage" on they might even see 8/?? but only get to pick 7 items priority. Pay is set by the Difficulty set in the MS Action Data and the contract type.
Code:
"salvagePotential" : 24, or [Salvage]24
Code:
"requirementList" : [], or [Requirement]
Code:
"contractDisplayStyle" : "BaseFlashpoint", or [ContractDisplayStyle]BaseFlashpoint
Code:
"scope" : "MID_CAMPAIGN", or [ContractScope]MID_CAMPAIGN
Total Lance Size, Lance and 'Mech Min/Max Tonnage Requirements
Not listed in the design templates, but present in the final .json file are parameters for setting the total Lance number, or Lance and individual 'Mech Tonnage restrictions. I'm going to have to use a different file's data for this, as a generated contract doesn't use these and they are not formatted in the template.txt.
Code:
"maxNumberOfPlayerUnits" : 4,
Code:
"lanceMinTonnage" : -1,
"lanceMaxTonnage" : -1,
"mechMinTonnages" : [
-1,
-1,
-1,
-1
],
"mechMaxTonnages" : [
50,
50,
50,
50
],
Code:
"lanceMinTonnage" : 320,
"lanceMaxTonnage" : -1,
"mechMinTonnages" : [
-1,
-1,
-1,
-1
],
"mechMaxTonnages" : [
-1,
-1,
-1,
-1
],
WARNING: The game doesn't like "lanceMaxTonnage" less than 120t for 2-4 slots. This 100t Max is OK for a SINGLE slot deployment (including forced units below)
With "mechMinTonnages" and "mechMaxTonnages" in the example above, each of the four units the player can bring must be 50t or less. It might be possible to edit each of the four values in the array, but I haven't tested that yet. I would assume it should work if you set up:
"mechMaxTonnages" : [
25,
50,
65,
85
]
It would allow a one slot with no greater than 25t, 50t, 65t and 85t respectively. You propably could mix and match Lance and 'Mech min/max limits but it starts to get confusing to explain to the player. I'd also consider following the guideline brackets set by HBS in the SimGameConstants.json for how to set your restrictions in the FP.json settings:
Code:
"LessThanThisWeightIsLightUnit" : 55,
"GreaterThanThisWeightIsHeavyUnit" : 60,
"LessThanThisTotalWeightIsLightLance" : 220,
"GreaterThanThisTotalWeightIsHeavyLance" : 240,
Try not to force consecutive drops with new tonnage restrictions in the consecutive mission! What I'm saying is, don't let a player launch thinking nothing is different and then suddenly forcing them to drop with <40t immediately without a ton of forewarning before launching the first non-consecutive mission. You might want to tell them the exact limits while they are able to refit and pass time in case they misjudged the restrictions. Given there is no way to exit the DropShip Deployment window, if the player has no valid units readied, they are stuck.
Try to give them time before a special restriction to ready the appropriate units. Now, if your FP is all one single restriction across all missions, you can do that as long as you warn the player in the initial conversation before forcing a mission on them.
Code:
"mapMood" : null,
Further Flashpoint Options Not In Template.txt
Code:
"overrideAutoCompleteDialogueId" : "DialogBucketDef_c_fp_theRaid_b2_defendBase",
"disableNegotations" : true,
"disableLanceConfiguration" : false,
"disableCancelButton" : true,
"disableAfterAction" : false,
"contractRewardOverride" : -1,
"travelOnly" : false,
"useTravelCostPenalty" : false,
"usesExpiration" : false,
"expirationTimeOverride" : -1,
"negotiatedSalary" : 0.25,
"negotiatedSalvage" : 0.75,
"excludedFromProceduralGeneration" : true,
SUPER IMPORTANT LINE TO ADD!
"excludedFromProceduralGeneration" : true,
You need this set to true to exclude this FP mission from being generated outside of the FP! Always double check every contracts "excludedFromProceduralGeneration" statement before releasing your FP.
When you are making a consecutive mission, you must remove the players ability to negotiate, cancel back out in to the simGame and set a fixed negotiation rate for them as below:
- "disableNegotations" : true,
- "disableCancelButton" : true,
- "negotiatedSalary" : 0.25,
- "negotiatedSalvage" : 0.75,
Editing Objectives
Code:
.json -
"contractObjectiveList" : [
{
"contractObjective" : {
"EncounterObjectGuid" : "6f5f8d17-70ed-44a8-acc0-ccf9258925aa"
},
"title" : "Defend a {TEAM_EMP.FactionDef.Demonym} R&D Facility",
"description" : "",
"isPrimary" : true,
"forPlayer" : "Player1",
"objectiveGuids" : [
"ca677a4d-19c8-4d0c-9c5e-3ed712081336",
"0e4ac925-d95a-4019-aeb0-0aa553830f46",
"d4d20990-fbeb-4f6e-81b7-7e94bba6a2c5",
"4bfadebf-a277-4ddb-8a36-f70ab7c0c68c",
"240577eb-b4b0-43b7-b2af-a94d692a022a",
"d01959cc-5ef1-4856-8918-1848c051368d"
]
}
.txt -
// Contract Objectives
[ContractObjective]Defend a {TEAM_EMP.FactionDef.Demonym} R&D Facility
[Description]
Right below that is the "objectiveList" or "// Battle Objectives" segment that details each objective and any bonus rewards for completing them.
Code:
.json -
"objectiveList" : [
{
"objective" : {
"EncounterObjectGuid" : "ca677a4d-19c8-4d0c-9c5e-3ed712081336"
},
"title" : "Defend Industrial Laboratory",
"description" : "Defend Base from Attackers",
"isPrimary" : true,
"OnSuccessResults" : [],
"OnFailureResults" : []
},
{
"objective" : {
"EncounterObjectGuid" : "0e4ac925-d95a-4019-aeb0-0aa553830f46"
},
"title" : "Destroy the Enemy Vanguard",
"description" : "",
"isPrimary" : false,
"OnSuccessResults" : [
{
"Scope" : "Company",
"Requirements" : null,
"AddedTags" : {
"items" : [],
"tagSetSourceFile" : ""
},
"RemovedTags" : {
"items" : [],
"tagSetSourceFile" : ""
},
"Stats" : [
{
"typeString" : "System.Single",
"name" : "ContractBonusRewardPct",
"value" : "0.1",
"set" : false,
"valueConstant" : null
}
],
"Actions" : [],
"ForceEvents" : [],
"TemporaryResult" : false,
"ResultDuration" : 0
}
],
"OnFailureResults" : []
},
{
"objective" : {
"EncounterObjectGuid" : "240577eb-b4b0-43b7-b2af-a94d692a022a"
},
"title" : "Ensure All Buildings Survive",
"description" : "",
"isPrimary" : false,
"OnSuccessResults" : [
{
"Scope" : "Company",
"Requirements" : null,
"AddedTags" : {
"items" : [],
"tagSetSourceFile" : ""
},
"RemovedTags" : {
"items" : [],
"tagSetSourceFile" : ""
},
"Stats" : [
{
"typeString" : "System.Single",
"name" : "ContractBonusRewardPct",
"value" : "0.2",
"set" : false,
"valueConstant" : null
}
],
"Actions" : [],
"ForceEvents" : [],
"TemporaryResult" : false,
"ResultDuration" : 0
}
],
"OnFailureResults" : []
},
{
"objective" : {
"EncounterObjectGuid" : "4bfadebf-a277-4ddb-8a36-f70ab7c0c68c"
},
"title" : "Hold Out for Reinforcements",
"description" : "Hold Out for Reinforcements",
"isPrimary" : true,
"OnSuccessResults" : [],
"OnFailureResults" : []
},
{
"objective" : {
"EncounterObjectGuid" : "d4d20990-fbeb-4f6e-81b7-7e94bba6a2c5"
},
"title" : "Escort Engineer APCs to Base Defenses",
"description" : "Escort Engineer APCs to Base Defenses in order to take control of them.",
"isPrimary" : false,
"OnSuccessResults" : [
{
"Scope" : "Company",
"Requirements" : null,
"AddedTags" : {
"items" : [],
"tagSetSourceFile" : ""
},
"RemovedTags" : {
"items" : [],
"tagSetSourceFile" : ""
},
"Stats" : [
{
"typeString" : "System.Single",
"name" : "ContractBonusRewardPct",
"value" : "0.1",
"set" : false,
"valueConstant" : null
}
],
"Actions" : [],
"ForceEvents" : [],
"TemporaryResult" : false,
"ResultDuration" : 0
}
],
"OnFailureResults" : []
},
{
"objective" : {
"EncounterObjectGuid" : "46d1c317-2344-4e53-aa9f-d9769edbb89d"
},
"title" : "Baddies Inbound",
"description" : "",
"isPrimary" : false,
"OnSuccessResults" : [],
"OnFailureResults" : []
},
{
"objective" : {
"EncounterObjectGuid" : "00d98f37-5576-43c3-ba74-953fb54bd497"
},
"title" : "Hidden Objective: Destroy the Third Lance",
"description" : "Hidden Objective: Destroy the Third Lance",
"isPrimary" : false,
"OnSuccessResults" : [],
"OnFailureResults" : []
},
{
"objective" : {
"EncounterObjectGuid" : "d01959cc-5ef1-4856-8918-1848c051368d"
},
"title" : "Baddies Inbound",
"description" : "",
"isPrimary" : false,
"OnSuccessResults" : [],
"OnFailureResults" : []
}
],
.txt -
// Battle Objectives
// Primary Objective
[Objective]Defend Industrial Laboratory
[Description]Defend Base from Attackers
// Optional Objective
[Objective]Destroy the Enemy Vanguard
[Description]
[OnSuccess]
[Result]Company|Stat|ContractBonusRewardPct|0.1
// Optional Objective
[Objective]Ensure All Buildings Survive
[Description]
[OnSuccess]
[Result]Company|Stat|ContractBonusRewardPct|0.2
// Primary Objective
[Objective]Hold Out for Reinforcements
[Description]Hold Out for Reinforcements
// Optional Objective
[Objective]Escort Engineer APCs to Base Defenses
[Description]Escort Engineer APCs to Base Defenses in order to take control of them.
[OnSuccess]
[Result]Company|Stat|ContractBonusRewardPct|0.1
// Optional Objective
[Objective]Baddies Inbound
[Description]
This means you can add or remove Tags, edit cash payouts by either % (as the default examples show) or by an absolute value and even do things like add/remove MedTech or MechTech levels. You should be able to assign whatever reward or penalty by using the same formatting from Event Results you may have already used in the FP or an Event.
Editing Optional Chunks
Code:
.json -
"chunkList" : [
{
"name" : "Chunk_EscortAPC_DefensiveTurrets (Bonus)",
"encounterChunk" : {
"EncounterObjectGuid" : "2340cc58-51b0-4db7-a9ff-f5ff08d86d01"
},
"enableChunkFromContract" : true,
"requirementList" : []
},
{
"name" : "Chunk_Wave3Attackers (Bonus)",
"encounterChunk" : {
"EncounterObjectGuid" : "5dca4e7f-ea4c-4582-8a4c-bb531e2c0754"
},
"enableChunkFromContract" : false,
"requirementList" : []
}
],
.txt-
// Optional Chunks
[OptionalChunk]Chunk_EscortAPC_DefensiveTurrets (Bonus)|on
[OptionalChunk]Chunk_Wave3Attackers (Bonus)|off
Inside this "chunkList" the chunk "Chunk_EscortAPC_DefensiveTurrets (Bonus)" is set to true and the chunk "Chunk_Wave3Attackers (Bonus)" is false. This is how you control which Lances will spawn and if other special events like turrets, DropShips and APCs appear in the contract. The Contracts of the FP References Sheet in the Resources and References tab above has most of the optional chunks listed, but is still incomplete at this time.
Editing Lances
Code:
.json -
{
"lanceSpawner" : {
"EncounterObjectGuid" : "4d39e72c-4f99-4cc6-8fe0-d4d18cad0063"
},
"name" : "Lance_Enemy_Wave1Attackers",
"lanceDefId" : "Tagged",
"lanceTagSet" : {
"items" : [
"lance_type_battle",
"lance_type_notallvehicles"
],
"tagSetSourceFile" : "tags/LanceTags"
},
"lanceExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/LanceTags"
},
"spawnEffectTags" : {
"items" : [],
"tagSetSourceFile" : "tags/SpawnEffectTags"
},
"lanceDifficultyAdjustment" : 0,
"selectedLanceDefId" : null,
"selectedLanceDifficulty" : 0,
"unitSpawnPointOverrideList" : [
{
"unitSpawnPoint" : {
"EncounterObjectGuid" : "52137684-666c-43d1-9528-99dc96471645"
},
"customUnitName" : null,
"customHeraldryDefId" : null,
"unitType" : "Mech",
"unitDefId" : "UseLance",
"unitTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/UnitTags"
},
"unitExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/UnitTags"
},
"spawnEffectTags" : {
"items" : [],
"tagSetSourceFile" : "tags/SpawnEffectTags"
},
"pilotDefId" : "pilotDef_InheritLance",
"pilotTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/PilotTags"
},
"pilotExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/PilotTags"
},
"selectedUnitType" : "UNDEFINED",
"selectedUnitDefId" : null,
"selectedPilotDefId" : null
},
{
"unitSpawnPoint" : {
"EncounterObjectGuid" : "1d32f819-a4d2-4df1-a66b-c641855e3b3b"
},
"customUnitName" : null,
"customHeraldryDefId" : null,
"unitType" : "Mech",
"unitDefId" : "UseLance",
"unitTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/UnitTags"
},
"unitExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/UnitTags"
},
"spawnEffectTags" : {
"items" : [],
"tagSetSourceFile" : "tags/SpawnEffectTags"
},
"pilotDefId" : "pilotDef_InheritLance",
"pilotTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/PilotTags"
},
"pilotExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/PilotTags"
},
"selectedUnitType" : "UNDEFINED",
"selectedUnitDefId" : null,
"selectedPilotDefId" : null
},
{
"unitSpawnPoint" : {
"EncounterObjectGuid" : "0b168027-919d-4d87-ae88-853711e26b67"
},
"customUnitName" : null,
"customHeraldryDefId" : null,
"unitType" : "Mech",
"unitDefId" : "UseLance",
"unitTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/UnitTags"
},
"unitExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/UnitTags"
},
"spawnEffectTags" : {
"items" : [],
"tagSetSourceFile" : "tags/SpawnEffectTags"
},
"pilotDefId" : "pilotDef_InheritLance",
"pilotTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/PilotTags"
},
"pilotExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/PilotTags"
},
"selectedUnitType" : "UNDEFINED",
"selectedUnitDefId" : null,
"selectedPilotDefId" : null
},
{
"unitSpawnPoint" : {
"EncounterObjectGuid" : "1843b49d-e943-46fc-88aa-954eb78be8d3"
},
"customUnitName" : null,
"customHeraldryDefId" : null,
"unitType" : "Mech",
"unitDefId" : "UseLance",
"unitTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/UnitTags"
},
"unitExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/UnitTags"
},
"spawnEffectTags" : {
"items" : [],
"tagSetSourceFile" : "tags/SpawnEffectTags"
},
"pilotDefId" : "pilotDef_InheritLance",
"pilotTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/PilotTags"
},
"pilotExcludedTagSet" : {
"items" : [],
"tagSetSourceFile" : "tags/PilotTags"
},
"selectedUnitType" : "UNDEFINED",
"selectedUnitDefId" : null,
"selectedPilotDefId" : null
}
]
},
.txt -
[Lance]Lance_Enemy_Wave1Attackers
[LanceDef]Tagged
// Tagged: lance def will be randomly chosen using tags field
[Tags]lance_type_battle|lance_type_notallvehicles
// upped the diff: medium & battle
[ExcludedTags]
[SpawnEffects]
[DifficultyAdjustment]0
// upped the diff.
// unit entries are only required if you want to override the lancedef (or if set to Manual)
[Unit]Mech
[UnitDef]UseLance
// UseLance: spawner will respect the lance def
[Tags]
[SpawnEffects]
[PilotDef]pilotDef_InheritLance
[Unit]Mech
[UnitDef]UseLance
// UseLance: spawner will respect the lance def
[Tags]
[SpawnEffects]
[PilotDef]pilotDef_InheritLance
[Unit]Mech
[UnitDef]UseLance
// UseLance: spawner will respect the lance def
[Tags]
[SpawnEffects]
[PilotDef]pilotDef_InheritLance
[Unit]Mech
[UnitDef]UseLance
// UseLance: spawner will respect the lance def
[Tags]
[SpawnEffects]
[PilotDef]pilotDef_InheritLance
The above example has the "Lance_Enemy_Wave1Attackers" and they are generating an entire procedural Lance. "lanceDefId" : "Tagged", sets this in motion and then below it you set the Tags you want that Lance to look for or exclude. In the example, it is looking for a Lance with the lags "lance_type_battle" and "lance_type_notallvehicles" with the difficulty scale of the Lance determined by the contract difficulty above, for FP's this is set in the MS Event Result Data for that mission. If this was a 10 Difficulty FP, it would look for lancedefs that meet all three of those conditions, as there is no further exclusions. Some of the valid options would be "lancedef_mixed_d10_dynamic_assaultBattle1" or "lancedef_mech_d10_dynamic_assaultBattle" and note that the second contains no vehicles where the first does, but none of them are all vehicle Lances. You can also tune up or down the difficulty of a Lance relative to the contract's difficulty with "lanceDifficultyAdjustment" : 0, and set to -2 would pull a lancedef 2 levels (one whole skull) lower. The "spawnEffectTags" is where you could set Lance-wide effects like starting at 50% armor using this example from another contract:
Code:
"spawnEffectTags" : {
"items" : [
"spawn_poorly_maintained_50"
],
"tagSetSourceFile" : "tags/SpawnEffectTags"
},
- "unitType" : "Mech", with either Mech, Vehicle or Turret as needed
- "unitDefId" : "UseLance", with the Id of the mechdef/vehicledef/turretdef
- "pilotDefId" : "pilotDef_InheritLance", with the Id of the pilotdef
- "customUnitName" : "",
- "customHeraldryDefId" : null,
- "customUnitName" : "Hired Goons - Lancer",
- "customHeraldryDefId" : "heraldrydef_steiner",
- "unitDefId" : "mechdef_zeus_ZEU-6S",
- "pilotDefId" : "pilot_d10_lancer",
You then repeat this process for each Lance and unit in play. You can assign 'Mechs and pilots to the player Lance in the same way, like Kamea in the campaign or the Hatchetman and pilot in Joint Venture. Keeping a Lance as "lanceDefId" : "Tagged", with Tag filters, and then manually assigning a single Lancemate would let you assign that one member and then let the Lance generator fill out the rest procedurally.
Editing Dialogue
The Dialogue is fairly strait forward, at first. You can copy and paste whole sections and just replace the "selectedCastDefId" or [Cast] with whoever you want to do the talking and edit the text as you wish. I don't recommend making these too long.
A problem arises with the mission finishing text. Some missions finish when you enter a Extraction Point, others end where you stand when the field is clear of all forces and objectives have been completed. This is where "Dialogue Buckets" come in. This is a special "bucket" or "pool" of chat boxes for a situation. We generally only need one.
Dialogue Buckets and DialogBucketDef
The line "overrideAutoCompleteDialogueId" : null, in a contract can be replaced with a custom DialogBucketDef for when your mission autocompletes. Some missions don't autocomplete or autocomplete by default (Battle) and may not need this.
- "overrideAutoCompleteDialogueId" : "DialogBucketDef_c_fp_theRaid_b2_defendBase",
{
"identifier" : "DialogBucketDef_c_fp_theRaid_b2_defendBase",
"DialogueContentIDs" : [
"Bkt_c_fp_theRaid_b2_defendBase"
]
}
"identifier" : "DialogBucketDef_c_fp_theRaid_b2_defendBase",
"DialogueContentIDs" : [
"Bkt_c_fp_theRaid_b2_defendBase"
]
}
This just says "Hey, use this Id when I'm called." The DialogueContentID is where the actual dialogue is. You usually will want to copy whatever is already in your mission success dialogue and add an opening line about "Coming in to pick-up where you are." or "All targets eliminated. Sit tight, and I can collect you from where you are at right now." and then the rest of the chatter.
Code:
{
"identifier" : "Bkt_c_fp_theRaid_b2_defendBase",
"contents" : [
{
"words" : "All targets eliminated. Sit tight, and I can collect you from where you are at right now.",
"wordsColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"selectedCastDefId" : "castDef_SumireDefault",
"emote" : "Default",
"dialogueOrigin" : "pilot",
"audioEventEntryIndex" : 0,
"audioEventEntryText" : "NONE",
"conversationIdx" : 0,
"cameraFocus" : {
"EncounterObjectGuid" : ""
},
"revealRadius" : -1
},
{
"words" : "Excellent work, Commander. Let's open this thing and see what's inside.",
"wordsColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"selectedCastDefId" : "castDef_DariusDefault",
"emote" : "Default",
"audioName" : "NONE",
"cameraFocusGuid" : "",
"cameraDistance" : "Far",
"cameraHeight" : "Default",
"revealRadius" : -1
},
{
"words" : "We detected The Muscles DropShip is feeling! Tiverton is free from these criminals and pirates once and for all.",
"wordsColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"selectedCastDefId" : "castDef_LocalsDefault",
"emote" : "Default",
"audioName" : "NONE",
"cameraFocusGuid" : "",
"cameraDistance" : "Far",
"cameraHeight" : "Default",
"revealRadius" : -1
},
{
"words" : "We know the truth, we will be back. Today, everyone gets to feel like they won, even if we've all lost something.",
"wordsColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"selectedCastDefId" : "castDef_TeamLeader_Target",
"emote" : "Default",
"audioName" : "NONE",
"cameraFocusGuid" : "",
"cameraDistance" : "Far",
"cameraHeight" : "Default",
"revealRadius" : -1
},
{
"words" : "Until next time\u2026",
"wordsColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"selectedCastDefId" : "castDef_TeamLeader_Target",
"emote" : "Default",
"audioName" : "NONE",
"cameraFocusGuid" : "",
"cameraDistance" : "Far",
"cameraHeight" : "Default",
"revealRadius" : -1
}
]
}
The Rewards
Flashpoint rewards are listed as a .csv file, or "Comma Separated Values" and if you open the file raw, it would a lot of items separated by commas. However, it's far easier to edit these types of files with an editor like CSVed or others available online. The itemCollection.csv's used for shop inventory and FP rewards have 4 columns:
- Item
- Type
- How many of that item
- "Drop Weight" of that item
Here we can see a custom reward table for "The Raid" with the first row, first column giving a title for the .csv table "itemCollection_loot_fp_reward_a_theRaid" and this is what you would type in for the rewards in the MS reward data or in the FP editor main screen as the reward displayed on the title card.
The second row defines a part of a 'Mech, a "mechdef_atlas_AS7-D-HT" and in the third column "1" it defines giving the player 1 of these parts. Take a look at the last two entries, the Gyro and Medium Lasers, you get 4 and 15 of those for this FP. The fourth column, the "weight" or "drop weight" is usually just 1 for a reward listing. For FP's, it will dish out every item on each row of this list in the amount defined in column three.
But what if you want to use a pool of potential items to roll from and give one or two to a player?
Referencing
To use the weighted pool of items, you need to reference another .csv. In rows 3-5 we see "Reference" type entries with a "1" in the third column. This will grant one item from those referenced .csv files.
Calling Other .csv Files
The reference lines must have the Id of the next .csv and lets take a look at the one stock .csv files called in the above reward list. The stock itemCollections are found in:
...\BATTLETECH\BattleTech_Data\StreamingAssets\data\itemCollections
Opening up "itemCollection_table_Weapon_SLDF.csv" and we only see 2 entries and no weapons. That's because this .csv file we referenced, calls two more .csv files based on RNG. Here, we see the first entry as a fourth column value of "4" and the second entry has "1."
This means the "itemCollection_Weapons_SLDF_uncommon.csv" has a 4/5 chance (80%) of being picked over the "itemCollection_Weapons_SLDF_rare.csv" which has the corresponding 1/5 chance (20%) of getting selected on any one roll. This is how weights work to adjust how common or rare an item or reference can be picked. This isn't out of 100 or any preset total, just add up all the weights in the table and divide you current item by the total to find the odds of it dropping.
Let's say we're feeling lucky and the "itemCollection_Weapons_SLDF_rare.csv" is selected.
Now we see actual weapons. So far, the original reward .csv called for 1 item from "itemCollection_table_Weapon_SLDF.csv" and on that one roll, "itemCollection_Weapons_SLDF_rare.csv" was selected, and now inside that table we will get one roll from the weapons in here. We can see items like the "Weapon_Gauss_Gauss_2-M9" have a weight of just 2 out of a total of 72, or 1/36 (2.78%) which oddly enough is the same as rolling a "12" on two six-sided dice. The other higher weight items like "Weapon_Laser_SmallLaserPulse_1-Maxell" have a 10/72 or 5/36 (13.89%) chance.
Now that you know how to drill through references to other .csv files and how the weights work, take some time to explore around the different possible pools of weapons and gear. You might find some odd stuff in the tables, like the CDA's being in the same rare 'Mech pool as a HGNb in the "itemCollection_Mechs_rare.csv" or other seemingly out of place rewards. If you ever need to find the type of item like "Weapon," "Mech" or "Upgrade" just find them in an existing table.
You would need to determine if your FP needs it's own custom reward list, and if that list would need to reference another custom .csv, or a stock one. These aren't too hard to make, but they can be hard to test, as they are at the end of the FP.
Testing Rewards
I recommend taking my "Sound of Music" FP in the Resources and References above and editing the rewards in the FP file to whatever file you want to test. This FP is just a conversation that you can cancel at any time and then hit the reward screen. This allows for rapid reward testing and you can see what kind of real end results will appear.
One note about the rewards screen - It doesn't show you the amount of the items rewarded in game. So if you see "DHS" on the rewards screen, it looks the same if it's one or a hundred. What I did was setup a "Sound of Music" save just before I accepted the FP but after selling all my gear and anything in storage. Remember, this is using a debug save for testing, so this is fine as long as you are careful. This gives me a clean slate once I'm out of the FP and I can easily see if I got multiples of the same item.
The Original Assets
You might want to create custom images, 'Mechs, Vehicles, cast members, heraldry, Lore descriptions and more. You don't need these, but they can add a special touch to your FP.
In general images should be in the .dds format, and try to keep them as small as possible. The performance modders have advised me to use .dds when possible as it is a lower overhead format for GFX processors compared to .png. However, there are cases where a file must be .png. You can find existing portraits, banners and such in the games files for examples. I'll keep the exact size and more detailed descriptions in the Advanced Editing Post below this one.
CastDef
Code:
{
"id" : "castDef_FP_MuscleDefault",
"internalName" : "FP_MuscleDefault",
"firstName" : "The",
"lastName" : "Muscle",
"callsign" : "",
"rank" : "Black Market Enforcer",
"gender" : "NonBinary",
"faction" : "AuriganPirates",
"sgCharType" : "UNSET",
"showRank" : true,
"showFirstName" : true,
"showCallsign" : false,
"showLastName" : true,
"localizeName" : false,
"defaultEmotePortrait" : {
"emote" : "Default",
"portraitAssetPath" : "../../Mods/Flashpoint-The-Raid-1.0.1/castSprites/guiTxrPort_Muscle_default_utr.png"
},
"emotePotraitList" : [
]
}
CastDef Portraits Must Be .png Images!
For whatever reason, CastDef portraits are defined by explicit file paths and must be in .png format. This portrait doesn't need to be added to the Version Manifest in ModTek, but you need to keep the file path in mind if you put the version number in your folder structure like "The Raid" does above. When I go to "Flashpoint-The-Raid-1.1.1" from 1.0.1 my file path will break unless I change this before release.
See the advanced FP Editing post below for more details on Art Asset Creation for CastDef Portraits.
Descriptions (Lore Tool-Tips)
Code:
{
"Id" : "LoreBattleROM",
"Name" : "BattleROM",
"Details" : "The equivalent of a Flight Data Recorder found in nearly every combat vehicle used today. Records hundreds of hours of sensor readings, video feeds and status updates in to a blastproof enclosure. Records can be played back as video or even fully recreated in simulator pods.",
"Icon" : ""
}
This is for the yellow text that you can mouse over in a description or conversation. You can insert these in to a conversation or event like this:
That last part "BattleROMs" is where you put the plaintext you want the user to read and the first part inside the inner brackets is where the Id for the description goes.[[DM.BaseDescriptionDefs[LoreBattleROM],BattleROMs]]
HeraldryDef
Code:
{
"Description" : {
"Cost" : 0,
"Rarity" : 1,
"Purchasable" : false,
"Manufacturer" : "null",
"Model" : "null",
"UIName" : "null",
"Id" : "heraldrydef_FP_theRaid_aces",
"Name" : "Ace Pirates",
"Details" : "Super Arrrrrrrr",
"Icon" : ""
},
"textureLogoID" : "uixTxrIcon_blackmarketEmblem",
"primaryMechColorID" : "Greyscale_05",
"secondaryMechColorID" : "Greyscale_05",
"tertiaryMechColorID" : "BrightRed_01"
}
The textureLogoID is not a direct filepath like what is needed for the CastDef. I believe you could add a custom emblem and call it here, as long as it starts with "uixTxrIcon_" and maybe not even that. Can't say I've tried a full custom yet, but I don't doubt it's possible. Keep in mind, only a very narrow selection of skins even shows this emblem. The Shadow Hawk DLC skin is one of those.
MechDef + ChassisDef
I'm not going to cover the basics of custom MechDef and ChassisDef's here, but there are some things you need to know for FPs.
Unit Tag:
"BLACKLISTED"
Make sure your MechDef has this tag added or else it will appear in random procgen contracts outside of your FP or also in Skirmish Mode. Note that this will also prevent the unit's salvage parts from appearing in the salvage pool, so take this in to consideration. It's also a good idea to make your own unique ChassisDef and add the "BLACKLISTED" tag if you really want to make sure the unit does not show up in salvage.
Making a custom enemy is a great way to increase the challenge without adding more units. However, you must keep in mind the difficulty rating of the FP as a whole, what kinds of custom units the player might have at that level and the rest of that mission OPFOR when you're making your custom unit. A simple and generally safe way to make a unit harder is to take the stock 'Mech and just add upgraded weapons in place of the stock components. This is a fast and easy way to add something different without having to create and balance many Lances of custom OPFOR.
PilotDef
Code:
{
"Description": {
"Id": "pilot_FP_ace_brawler",
"Name": "Ace Brawler",
"FirstName": "Ace Brawler",
"LastName": "NONE",
"Callsign": "Ace Brawler",
"Gender": "Female",
"Faction": "Davion",
"Age": 30,
"Details": "NONE",
"Icon": "Wildfire"
},
"BaseGunnery": "10",
"BonusGunnery": 0,
"BasePiloting": "10",
"BonusPiloting": 0,
"BaseGuts": "10",
"BonusGuts": 0,
"BaseTactics": "10",
"BonusTactics": 0,
"ExperienceUnspent": 0,
"ExperienceSpent": 0,
"Injuries": 0,
"Health": 3,
"LethalInjury": false,
"Incapacitated": false,
"Morale": 0,
"Voice": "f_overload01",
"abilityDefNames": [
"AbilityDefGu5",
"AbilityDefGu8",
"AbilityDefP5",
"TraitDefUnsteadySet60",
"TraitDefEvasiveChargeAddOne",
"TraitDefSprintIncrease20",
"TraitDefUnsteadySet80",
"TraitDefEvasiveChargeAddTwo",
"TraitDefHealthAddOne",
"TraitDefRefireReduceOne",
"TraitDefOverheatAddFifteen",
"TraitDefHealthAddTwo",
"TraitDefRefireReduceTwo",
"TraitDefOverheatAddThirty",
"TraitDefHealthAddThree",
"TraitDefIndirectReduceOne",
"TraitDefMinRangeReduce45",
"TraitDefCalledShotImprove",
"TraitDefIndirectReduceTwo",
"TraitDefMinRangeReduce90",
"TraitDefCalledShotMaster",
"TraitDefIndirectReduceThree"
],
"AIPersonality": "Undefined",
"PilotTags": {
"items": [
"pilot_npc_brawler",
"pilot_npc_dynamic",
"BLACKLISTED"
],
"tagSetSourceFile": ""
},
"PilotCost": 0
}
Make sure to add the "BLACKLISTED" tag on your pilots! If you don't they'll show up outside your FP in random contracts.
VehicleDef + VehicleChassisDef
Same as MechDef's above, make sure you add the "BLACKLISTED" tag to prevent a custom vehicle from showing up in procgen contracts.
Special note for SRM/LRM Carriers: They don't have turrets and have some bugs that come with it. There are some mods out there like the Vehicle Improvment Project that fix this by adding a turret to the stock vehicle and the associated VehicleChassisDef. If you have a custom SRM/LRM carrier with or without a turret, make your own VehicleChassisDef to match it to prevent mis-matches and failure to load.
The Loading
This is done via ModTek. You will need to use the mod.json format documented here and here. You will need to add any files you want added in to your mod.json manifest. I recommend keeping the same kind of folder structure as HBS in the "BATTLETECH\BattleTech_Data\StreamingAssets\data" folder.
The one exception is .png portraits used for custom castdef.jsons. These are called by direct file paths in the castdef and don't need to be added to the ModTek manifest, they can be, but don't need to. I named my folder "castSprites" to keep it separate from sprites I want loaded in for other things.
The mod.json and folder structure for "The Raid" looks like this:
Code:
{
"Name": "Flashpoint_The_Raid",
"Enabled": true,
"Version": "1.0.0",
"Description": "Flashpoint - The Raid: Tiverton wants the Black Market out, are you in?",
"Author": "amechwarrior",
"DependsOn": [ "Flashpoint_Stock_Photos" ],
"OptionallyDependsOn": [ "cFixes" ],
"Manifest": [
{ "Type": "BaseDescriptionDef", "Path": "descriptions" },
{ "Type": "CastDef", "Path": "cast" },
{ "Type": "ChassisDef", "Path": "chassis" },
{ "Type": "ContractOverride", "Path": "contracts" },
{ "Type": "ConversationContent", "Path": "dialogue_buckets" },
{ "Type": "DialogBucketDef", "Path": "conversationBuckets" },
{ "Type": "FlashpointDef", "Path": "flashpoints" },
{ "Type": "HeraldryDef", "Path": "heraldry" },
{ "Type": "ItemCollectionDef", "Path": "itemCollections" },
{ "Type": "MechDef", "Path": "mech" },
{ "Type": "PilotDef", "Path": "pilot" },
{ "Type": "SimGameConversations", "Path": "simGameConversations" },
{ "Type": "SimGameEventDef", "Path": "events" },
{ "Type": "SimGameMilestoneSet", "Path": "milestoneSets" },
{ "Type": "Sprite", "Path": "sprites" },
{ "Type": "Texture2D", "Path": "textures", "AddToAddendum": "ConversationTexture" },
{ "Type": "VehicleDef", "Path": "vehicle" }
]
}
I'm assuming you built your FP and MS files in a stand-alone folder suggested above. You will need to manually copy them over in to your FP's mod folder, in to their appropriate individual folder each time you save with the editor.
[Mod edit: Reminder. No unapproved links]
Attachments
Last edited: