MagicBounty writing tutorial

From Starsector Wiki
Jump to navigation Jump to search

Introduction

A simple MagicBounty flavor text

MagicLib offers a simple no-code-required, no-rules.csv, solution to add unique bounties to the game. It presents itself as an "unnofficial bounty board" that can be consulted in bars around the sector. (imagine a space version of Craig's List mixed with 4-chan's anonymity and loose moderation). Job offers can be ignored or dissmissed entirely to never see them again, but once accepted they will have a completion deadline and one of 4 objectives. The content displayed with the offer is entirely at the discretion of the author: from nothing but a flavor text with a reward to the exact location and enemy fleet's composition, you define what will be and won't be known by the player.

Tools

VSCode interface with reference file on the left and working file on the right.

While any text editor can be used to create and edit JSON files, but I strongly suggest using Visual Studio Code, with the Hjson plugin. The JSON format is somewhat finicky, using that program will make your life much easier with pretty colors, section collapsing and highlights of some basic mistakes. Make sure to pick "Hjson" highlighting with the "Select Laguage Mode" button to the bottom right instead of "json" or "regular text", it can easily be missed. Using "dev mode" will also enable a LOT of messages in the debug console and the log, detailing each steps of the bounty loading and creation. It can greatly help you find why you aren't getting desired results, or where you might have made a mistake.

Word of caution

Always refer yourself to the MagicLib main article for finding documentation about the latest version of the file. More parameters and functionalities may be added over time that you may want to take advantage of. Additionally, if you have a compelling idea that would require a new feature, do not hesitate to propose it.

Where to start

The bounty is defined as a "JSON" file that gets merged and added to a pool of bounties. More specifically it uses the Hjson formatting that allows the use of # to ignore a line or add comments. If you are not familiar with this type of file, I suggest to read at least a short primer on it. Most errors comes from missing a comma, or not using [ ] and { } where it is appropriate. Fortunately MagicLib includes a blank file in the appropriate MagicLib\data\config\modFiles folder to avoid most mistakes. Copy that file to the same location in your mod, rename it from magicBounty_data_BLANK.json to magicBounty_data.json and you will be ready to start writing. Please note that most parameters are either optional or have a default value to cover most comon cases. If you are satified with those, you can safely remove any unused parameter.

ID and REQUIREMENTS

{
    "bountyID":{
    
        "required_mods_id": ["modA", "modB"], # Default: no values. List the required mods for this bounty

> bountyID is the unique designation of that bounty offer. I strongly suggest to use a prefix to ensure it does not get overwritten, or overwrites someone else's bounty.

> required_mods_id lists the ID of mods that are required for your bounty. Remove that parameter if there are none other than your mod itself to function.

TRIGGERS

"Can the bounty be offered here and now?"

The triggers define where and when the bounty will be offered. While they are all optional, I would suggest you narrow down the places where your bounty is offered, if only to avoid spamming it everywhere.

        "trigger_market_id": ["market_name"], # Default: no values. Can default to the other preferences if those are defined and the location doesn't exists due to Nexerelin random mode. 
                                              # This beats all other conditions; a job will ALWAYS show in this market, even if other conditions fail.
        "trigger_marketFaction_any": ["faction"], # Default: no values. markets of these factions will show the bounty (if other conditions are met).
        "trigger_marketFaction_alliedWith": true, # Default: false. if true, markets of all factions whose relationship is at least FAVORABLE to ANY ONE of the factions above will show the bounty (if other conditions are met).
        "trigger_marketFaction_none": ["other_faction"], # Default: no values. markets of factions listed here will never carry the bounty, regardless of other conditions.
        "trigger_marketFaction_enemyWith": false, # Default: false. If true, markets of all factions whose relationship is HOSTILE to EVERY ONE (ALL) of the factions above. Beware when using this parameter with multiple excluded factions.
        "trigger_market_minSize": 3, # Default: 0. The minimum size of the market.
        "trigger_player_minLevel": 15, # Default: 0. The minimum level of the player.
        "trigger_min_fleet_size": 25, # Default: 0. The minimum player fleet "power" based on Fleet Points (not Deployment Points) with some multipliers for officers and player levels. Can be used to prevent exploits such as picking ships in storage to reduce the size of the bounty fleet. 
        "trigger_min_days_elapsed": 360, # Default: 0. The minimum number of days that must have elapsed.
        "trigger_weight_mult": 0.25, # Default: -1. Simple frequency multiplier when several bounties compete for limited board slots. Weights are added together, then one is picked at random, with higher weights having a higher chance. Default bounty memKeys of note:
		"trigger_memKeys_all": { # Default: no values. The job will only show if ALL of the listed memKeys exist with the specified boolean value.
		    # $job_memKey_succeeded set to true if the job has been successfully completed
            # $job_memKey_failed set to true if the job required the destruction of a flagship and the player salvaged it instead
            # $job_memKey_expired set to true if the job deadline expired, ended without player involvment, or was permanently dissmissed
            # $job_memKey set to false when the job has been picked up, true once concluded regardless of the result
            "$triggerKey":true,
        },
        "trigger_memKeys_any": { # Default: no values. The job will show if ANY of the listed memKeys exist with the specified boolean value.
            "$triggerKey":true,
        },
        "trigger_playerRelationship_atLeast": { # Default: no values. This job will require the player to have the specified relationship or HIGHER with the specified faction(s).
            "factionLikedId":0.25,
        },
        "trigger_playerRelationship_atMost": { # Default: no values. This job will require the player to have the specified relationship or LOWER with the specified faction(s).
            "factionDislikedId":-0.5,
        },

A lot of parameters are self-explanatory, but here are a few more details:

The bounty board is available in this bar

> trigger_market_id : If there are market IDs defined, the offer will ONLY be available at these. However you may still want to define fallback options so that players using Nexerelin "Random Core Worlds" can still have access to it in their game, such as defining a faction markets.

> trigger_marketFaction_any and trigger_marketFaction_alliedWith : These allow you to enable every markets from a given faction list to offer your bounty, along their allies if desired (reputation level of welcoming and up).

> trigger_marketFaction_none and trigger_marketFaction_enemyWith  : The former designate the factions whose markets CANNOT offer the bounty, but also to limit the offer to market from factions that are hostile to them (reputation level of hostile and lower)

Please note that defining both allowed markets with allies, and forbidden markets with enemies can make your bounty extremely widely available, especially in large modded games with random relationships.

Two jobs are available

> trigger_player_minLevel and trigger_min_fleet_size : These define player-bound progress requirements. Min level is a campaign advancement threshold, but min fleet size is variable. The later can be easier to use if you have a bounty fleet that scales to a minimum size, so that it is only offered when the player has a fighting chance.

> trigger_memKeys_all and trigger_memKeys_any : memkeys are variables stored in memory, they can be created and altered by scripts or events from both vanilla and mods. For example there is a $gaATG_missionCompleted memkey set when completing the main quest. Each MagicBounty creates a few of their own, therefore you can use these to create a simple chain of bounties offered one after the other, or even with some light branching depending on the outcome. Please note that MagicBounty only supports boolean memkeys. Additionally if you can use trigger_memKeys_all as "memKey_none" by adding all the undesired memkeys with the opposite value.

Each MagicBounty will add the following memkeys depending on their status, where "job_memKey" is a string defined in the next section of the bounty data:

  • $job_memKey_succeeded : set to true if the job has been successfully completed
  • $job_memKey_failed : set to true if the job required the destruction of a flagship and the player salvaged it instead
  • $job_memKey_expired : set to true if the job deadline expired, ended without player involvment, or was permanently dissmissed
  • $job_memKey : set to false when the job has been picked up, true once concluded regardless of the result

Another memKeys of interest setup by MagicLib is $IBB_ACTIVE, set to true and false when Ship and Weapon Pack's Interstellar Bounty Board is present and enabled or not. Meaning that you can create a backup bounty with a unique ship that was only offered as IBB, that will only show up when IBBs are not available.

> trigger_playerRelationship_atLeast, and trigger_playerRelationship_atMost : These define relationship requirement from the player to any given faction, for example they can ensure the player is already hostile to a target's faction, or on the contrary trusted enough by the giver's faction.

A not-too-fancy bounty typically would just set three parameters: "trigger_marketFaction_any" with the offering faction, "trigger_min_fleet_size" with a falue similar to the min bounty size, and either set a trigger_playerRelationship_atLeast minimum with the offering faction or trigger_playerRelationship_atMost maximum against the target faction.

BOUNTY DESCRIPTION

"What is this job about?"

These parameters define what will be shown to the player once they connect to the bounty board in a bar. This is where the bulk of the work takes place.

        "job_name": "job name", # Default: "Unnamed job". Job name shown in the dialog pick list
        "job_description": "Long form description of the job", # Default: blank. The description shown upon selecting the job.
                                                               # \n creates a line break, for example "Line one.\nLine two."
															   # \" adds quotation marks.
                                                               # == brackets create a highlight, for example "Text ==highlight== text."
                                                               # ^ uppercase the following letter of a text variable, for example "^$heIsSheIsTheyAre turning angry."
                                                               # %% allow the use of %, otherwise it will be interpreted as an escape character. 
                                                               # $sonDaughterChild based on bounty commander gender.
                                                               # $fatherMotherParent
                                                               # $manWomanPerson
                                                               # $heSheThey
                                                               # $himHerThem
                                                               # $hisHerTheir
                                                               # $heIsSheIsTheyAre
                                                               # $himslefHerselfThemselves
                                                               # $system The star system that the bounty fleet is in.
                                                               # $location The body that the bounty fleet has been placed near.
                                                               # $shipName The name of the bounty flagship.
                                                               # $faction The name of the faction (with article) of the bounty fleet.
                                                               # $reward The amount of credits being given as a reward.
                                                               # $name The name of the bounty commander.
                                                               # $firstName The first name of the bounty commander.
                                                               # $lastName The last name of the bounty commander.
                                                               # $constellation The constellation that the bounty fleet is in.
                                                               # $shipFleet base on either the target being a ship alone, or a fleet.
        "job_comm_reply": "Reply of the enemy to your hail", # Default: none. The text shown if the player opens comms with the bounty fleet, 
                                                             # If set as an empty string, displays "The other $shipOrFleet does not answer to your hails."
                                                             # If not set, defaults to the regular comm reply for the fleet's faction.
        "job_intel_success": "Short text displayed in the intel", # Default: not shown. Short conclusion text shown in the intel object after the job has been COMPLETED SUCCESSFULLY.
        "job_intel_failure": "Short text displayed in the intel", # Default: not shown. Short conclusion text shown in the intel object after the job has been failed through FLAGSHIP RECOVERY.
        "job_intel_expired": "Short text displayed in the intel", # Default: not shown. Short conclusion text shown in the intel object after the job has EXPIRED.
        "job_forFaction": "faction_offering_the_job", # Default: no faction. Note that unless "job_reputation_reward" is set to 0, successfully completing a bounty will improve relations by 5 points.
        "job_deadline": 360, # Default: no limit. The number of days to complete the bounty.
        "job_credit_reward": 9000, # Default: no credit reward. Number of credits to award the player on successful completion.
        "job_reward_scaling": 1.0, # Default: no scaling/bonus. Bonus credits based on FP. Bonus is the specified number multiplied by how many FP the bounty fleet was over their base FP.
        "job_reputation_reward":5, # Default: 5 rep points. Reputation benefit with the faction posting the bounty, if any, in case of success. Set to 0 or less to disable, does not scale
        "job_item_reward": { # Default: no item rewards. Lists special items that will be added to the post-battle loot. First value is the item id, second is the number to give the player.
            # Using the same syntax as Console Commands, blueprints may be added. ["fighter_bp", "industry_bp", "modspec", "ship_bp", "weapon_bp"]
            "item_A":1,
            "ship_bp shipId": 1 
        },
        "job_type":"assassination", # Default: assassination.
                # assassination: required only to disable the flagship, may recover it.
                # destruction: requires the complete destruction of the flagship without recovery.
                # obliteration: requires the complete destruction or disabling of the enemy fleet, may recover.
                # neutralisation: requires the destruction or disabling of 2/3rd of the enemy fleet, may recover.
        "job_show_type": true, # Default: true. Make sure to explain the mission objective in the bounty description if you choose to not use the default display.
        "job_show_captain": false, # Default: false. Whether to show the bounty fleet captain on the job board. If false, shows the flag of the giving faction.
        "job_show_fleet": "preset", # Default: "vanilla".
                # How much of the fleet to show on the bounty board.
				# none
                # text: "The intel assessment notes the target fleet may contain upwards of %s ships."
                # flagship: only shows an image of the flagship
                # flagshipText: shows an image of the flagships and a text with the number of other ships
                # preset: only show an image of the Flagship and the preset fleet
                # presetText: show an image of the Flagship and the preset fleet, plus a text with the number of other ships
                # vanilla: shows the Flagship and the 9 biggest ships of the fleet, plus a text with the number of other ships
                # all: show an image of all the ships in the fleet.
        "job_show_distance": "vague", # Default: "none".
                # How precisely the distance to the target is shown on the bounty board.
                # none: Do not show the distance.
                # vague: "The target is located somewhere in the vicinity of the core worlds."
                # distance: "It is located roughly %s LY away from your current position."
				# vanilla: "The target is located near a giant in a system with a yellow primary star, in the Nebulon constellation." Also shows a map during the bar dialog
                # vanillaDistance: "The target is located near a giant in a system with a yellow primary star, in the Nebulon constellation. It is located roughly %s LY away from your current position." Also shows a map during the bar dialog
				# exact: "The target is located near X in the Y system." Also shows a map during the bar dialog
		"job_show_arrow": false, # Default: false. Whether to show an arrow on the Intel map pointing from the start to the bounty target location. Should only be enabled when there is a good reason, to match vanilla.
        "job_difficultyDescription": "auto",  # Default: auto description shown. "none": no description, "auto": bounty board describes how dangerous the bounty is, any other text: bounty board displays the text.
        "job_pick_option": "Accept the job", # Default: "Accept the job". The text option that, when selected, accepts the bounty job.
        "job_pick_script": "data.script.FancyScriptThatDoStuff", # Default: no script. Triggered after accepting, can be used to trigger further scripts when the mission is taken, for example you may want to have competing bounty hunters
        "job_memKey":"$jobMemKey",	# Defaults to "$bountyId", memKeys always start with "$". The specified memkey will be set to false when the job is accepted, then true if it is completed.
        "job_conclusion_script":"data.script.FancyScriptThatDoStuff", # Default: no script. Can be used to give additional rewards or add further consequences in case of failure using memkeys to check the outcome

> job_name : This is simply the title of the bounty that will be listed during the bar event and shown at the top of the intel item. You should try to keep it short to avoid overflowing from the small intel title bar, but also endearing.

The job_description explains the situation around the bounty offer

> job_description : This is the narration of your bounty, where you define the different actors and their motivations. It can be long but be mindful that the dialog window of the bar event is not large, and long texts will require the player to scroll back up to read the begining. Additionally, several formating elements require special characters such as \n to start a new line, or == brackets to highlight a sentence. You also have several variables available to account for procedural components of your bounty, such as the random system where is will be located, or the target's commander random gender should you not define it. You can find the full list of these variables in the code block above.

The job board itself is deliberately loosely defined so that it can be freely used by everyone for any purpose. You can conceptualize it as an "online" forum that has some degree of authentification from both parties (poster and reader) but also preventing either to see who is the other unless explicitely allowed to. It can support any type of posting: text, audio, video... What is does not have however is a physical presence.

The bounty details shown after the flavor text

> job_comm_reply : This optional field will be used when trying to establish communication with the bounty target. If it is absent, the fleet will reply with the vanilla dialog, if it is set as a "" empty field, the reply will be swapped for a generic "The other fleet does not reply to your hails." This field is ideal to further the context of the bounty, establish new motivations from the other side, or maybe give the player missing informations so that they might reconsider fighting this fleet.

> job_intel_success, job_intel_failure, and job_intel_expired : Those three field are optional texts that will be shown in the intel screen object for the bounty once it reached some conclusion. "Success" is obviously for when the player accomplished the objective, "failure" is currently only used when the player had to completely destroy a target ship but instead salvaged it, "expired" is used when the bounty ran out of time, but also if someone else took it out. Those texts can be used to bring some closure or to expand on the consequences of that mission.

Intel Screen with a MagicBounty item

> job_forFaction : The faction that posted the bounty, can be left blank for an anonymous or unaffiliated posting. It is required if there is a reputation reward for completing the bounty.

> job_credit_reward, job_reward_scaling, job_reputation_reward, and job_item_reward : These define what the player will gain from completing the bounty. Only the credit reward will be explicitely shown in the detail section of the bounty post, you'll have to define other reward in the bounty description.

> job_reputation_reward is the reputation gain with the offering faction. It has a default value of 5 points in case of success and twice that as penalty for failling a mission requiring the complete destruction of a flagship. Set it to 0 if you don't want any reputation reward. Obviously it it not used if there is no offering faction.

> job_reward_scaling only affects credits, and requires the target fleet to have some minimal FP size. It is a multiplier applied to the relative scale of the player fleet compared to the minimum bounty fleet:

credit reward = job_credit_reward + job_credit_reward * job_reward_scaling * player fleet scale

A credit reward scaling should always be paired with a bounty fleet scaling, and usually at a lower rate. Importantly, the credit scaling cannot offer less than the base reward.

> job_type : There are currently four job types available.

  • assassination is the classic bounty. Disable the enemy flagships, get paid. Simple and easy.
  • destruction is a variant of assassination missions, were the player is forbidden from recovering the flagship. It can be used to propose difficult choices between a hefty pay-day, or a fancy ship to recover.
  • obliteration requires the complete destruction of the enemy fleet to the last ship. This type should be used very carefully as it can be infuriating to chase a lone escaping frigate with a gigantic late-game fleet.
  • neutralisation on the other hand only requires the destruction of 66% of the enemy fleet. The flagship survival is irrelevant here.

> job_show_type : A boolean determining if the type of job should be displayed along the bounty details. This should only be set to false for compelling narrative reasons, and if the player is able to understand what is expected from them with the flavor text.

> job_show_captain : A boolean determining if the captain's portrait should be displayed next to the flavor text.

> job_show_fleet : There are several options to determine how much of the target fleet will be shown along the bounty details.

  • none obviously does not show anything. Beware that it can be difficult to accept a bounty against a target you know nothing about, make sure it is offered at an appropriate power level or gives an attractive reward to take that risk. Only use this if there is a compelling reason to.
  • text only indicates the number of ships in the target fleet. Again that is very vague and should only be used for a very intentional reason.
  • flagship shows the flagship itself but that is it.
  • flagshipText shows the flagship along a text with the number of other ships in the target fleet.
  • preset shows the flagship along every handpicked escort ships in the fleet.
  • presetText shows the flagship with every handpicked escort ships along a text with the number of other ships in the target fleet.
  • vanilla shows the flagship with the 9 largest ships in the fleet along a text with the number of other ships. This is the default setting.
  • all shows the entire fleet.

Note that you should always use the highest level of display compatible with your intention. For example, if the bounty fleet only has a flagships plus a few preset ships and you want to show all of them, use "all" rather than "preset" so that the section's text says "Full fleet information is available" rather than "Partial fleet information is available".

> job_show_distance : How precisely the position of the target is known.

  • none obviously does not indicate any position at all. Once again this should only be used with a deliberate intention due to how confusing it will be. Also note that once the bounty is accepted, the intel element WILL point the player toward the constellation where the target is.
  • vague indicates if the target is in the core worlds, near the core worlds or in the fringes of the sector (roughtly divided in thirds of the longest side). Like "none", once the bounty is accepted the intel element WILL point the player toward the constellation where the target is.
  • distance indicates the rought distance in light years from the current position of the player. Like "none", once the bounty is accepted the intel element WILL point the player toward the constellation where the target is.
  • vanilla matches the vanilla way of presenting bounties with a constellation and a vague indication of the star color/size plus an object in the system. This setting will also highlight the general direction in a sector map next to the flavor text.
  • vanillaDistance same as the previous setting with the distance in light-years. This is the default setting. Somewhat less useful since 0.95.1 now that a map is displayed next to the flavor text.
  • exact inticates the exact position inside a specific system, with the distance in light-years and a map next to the flavor text.

> job_show_arrow : set if an arrow be displayed on the intel map. Note that vanilla bounties do not display such arrow, it should only be enabled for deliberate reasons.

> job_difficultyDescription : this section is displayed in the bounty details to help the player decide if they have the fleet to take on the bounty. It can use a custom hand-written text, or display a rough estimate of the difficulty to expect by using "auto".

> job_pick_option : a very optional field if you want to set a different reply for the player to accept the bounty than "Accept the job".

> job_pick_script and job_conclusion_script : MagicBounty allows you to fire script upon taking a bounty and concluding it respectively. Those can be used to do pretty much anything from spawning a concurrent bounty-hunter fleet you have to beat to the pot, or to trigger consequences for the completion. To enable the script, you will have to add a simple line to data/campaign/rules.csv :

a_unique_rule_id,"job_pick_script_id_from_magicBounty_data",,"script_to_fire_in_data.scripts.bounty.rulecmd",,,

See MagicLib's rules.csv file and src/data/scripts/bounty/rulecmd/BountyScriptExample.java for an example.

> job_memKey : the memKey associated with the bounty. Note that is should always start with the "$" character. By default the memKey will be set to "$bountyID". This memKey will be added to the sector's memory as false when the bounty is taken, then true when the bounty is concluded, and it will be added to the target fleet memory.

A not-too-fancy bounty would fill job_name, job_description, and job_intel_success; set job_forFaction, job_deadline and job_credit_reward; use the assassination type and the auto threat assessment; then let everything else by default.

TARGET EXISTING FLEET

This is a special function allowing you to place a bounty on a fleet that is already present in the sector. Typically a fleet placed somewhere during the sector's generation and that can be encountered through regular exploration, but that you may want to reveal to the player once they reach an appropriate power level.

		"existing_target_memkey":"$memKey",

Beware, if this parameter is set, the bounty will ONLY become available if a fleet with this memKey is alive, it overrides every folowing parameter. If more than one fleet has this memKey, the first one found will be picked.

TARGET COMMANDER

"Who am I fighting?"

These parameters define the officer in charge of the target fleet. They are all optional if you just want to use the default random character that is generated with the fleet.

        "target_first_name":"Firstname", # Default: randomly selected based on faction.
        "target_last_name":"Lastname", # Default: randomly selected based on faction.
        "target_portrait":"portraitId", # Default: randomly selected based on faction. Id of the sprite in settings.json/graphics/characters or full file path.
        "target_gender":"ANY", # Default: ANY. [ANY, UNDEFINED, MALE, FEMALE] ANY will randomly pick between male and female to avoid oddities and issues with texts and portraits.
        "target_rank": "Captain", # Default: "citizen". Rank from campaign.ids.Ranks [https://jaghaimo.github.io/starsector-api/classcom_1_1fs_1_1starfarer_1_1api_1_1impl_1_1campaign_1_1ids_1_1Ranks.html]
        "target_post": "Fleet Commander", # Default: "spacer". Post from campaign.ids.Ranks (yes, Ranks, posts are the bottom half). [https://jaghaimo.github.io/starsector-api/classcom_1_1fs_1_1starfarer_1_1api_1_1impl_1_1campaign_1_1ids_1_1Ranks.html]
        "target_personality": "aggressive", # Default: Randomly selected. Personality from campaign.ids.Personalities ("timid", "cautious", "steady", "aggressive", "reckless")
        "target_aiCoreId": null, # Default: null (not an AI). The AI Core id of the bounty commander. Core will be dropped as loot. Options: [ null, "gamma_core", "beta_core", "alpha_core" ]
        "target_level": 1, # Default: 0. The level of the bounty commander
        "target_elite_skills":2, # Default: vanilla setting (2 by default). Overrides the regular number of elite skills, set to 0 to not use elite skills.
        "target_skill_preference": "ANY", # Default: "ANY". 
		    # YES_ENERGY_YES_BALLISTIC_YES_MISSILE_YES_DEFENSE,
		    # YES_ENERGY_YES_BALLISTIC_NO_MISSILE_YES_DEFENSE,
		    # YES_ENERGY_YES_BALLISTIC_YES_MISSILE_NO_DEFENSE,
		    # YES_ENERGY_YES_BALLISTIC_NO_MISSILE_NO_DEFENSE,
		    # YES_ENERGY_NO_BALLISTIC_YES_MISSILE_YES_DEFENSE,
		    # YES_ENERGY_NO_BALLISTIC_NO_MISSILE_YES_DEFENSE,
		    # YES_ENERGY_NO_BALLISTIC_YES_MISSILE_NO_DEFENSE,
		    # YES_ENERGY_NO_BALLISTIC_NO_MISSILE_NO_DEFENSE,
		    # NO_ENERGY_YES_BALLISTIC_YES_MISSILE_YES_DEFENSE,
		    # NO_ENERGY_YES_BALLISTIC_NO_MISSILE_YES_DEFENSE,
		    # NO_ENERGY_YES_BALLISTIC_YES_MISSILE_NO_DEFENSE,
		    # NO_ENERGY_YES_BALLISTIC_NO_MISSILE_NO_DEFENSE,
		    # NO_ENERGY_NO_BALLISTIC_YES_MISSILE_YES_DEFENSE,
		    # NO_ENERGY_NO_BALLISTIC_NO_MISSILE_YES_DEFENSE,
		    # NO_ENERGY_NO_BALLISTIC_YES_MISSILE_NO_DEFENSE,
		    # NO_ENERGY_NO_BALLISTIC_NO_MISSILE_NO_DEFENSE,
		    # ANY (from OfficerManagerEvent.SkillPickPreference)
        "target_skills": { # Default: empty. REMOVES ALL RANDOM SKILLS, set level 1 for normal skill, level 2 for elite.
            "skillnameA":1,
            "skillnameB":2,
            "skillnameC":1,
        },

> target_portrait : Define the portrait used by the commander. You can either enter the full path to the file ex: "target_portrait": "graphics/portraits/portrait17.png", (make sure the portrait is loaded on game launch) or use the id from the graphic/characters section of the settings. If no portrait is set a random faction-specific and gender appropriate one will be selected.

> target_gender : Sets the gender of the commander, can be MALE, FEMALE, ANY for random male or female, or UNDEFINED for specifically non-gendered character.

> target_rank and target_post : Define the rank and post of the commander. Available ranks and posts can be found in the API at campaign.ids.Ranks, or in the MagicLib discord.

> target_skills : Can be used to override all random skills, and instead define a specific build. Skills can be made level 2 for elite benefits or 1 for the normal effect. This should only be used if you need certain skills to be active.

While all these parameters are entirely optional, it is good practive to at least set target_level, target_skill_preference, target_rank, target_post, and usually target_personality. Otherwise the game will only generate a level 1 "citizen" in charge of the bounty fleet.

TARGET FLEET

"What am I fighting?"

These parameters define the bounty fleet itself.

        "fleet_name":"Fleet Name", # Default: no name.
        "fleet_faction": "ML_bounty", # Required. The faction id from [https://jaghaimo.github.io/starsector-api/classcom_1_1fs_1_1starfarer_1_1api_1_1impl_1_1campaign_1_1ids_1_1Factions.html] or a custom faction id.
        # MagicLib includes a utility bounty faction that is forced to be neutral to everyone but the player under the id ["ML_bounty"].
        "fleet_flagship_variant":"buffalo2_FS", # Required. The variant ID to use for the Flagship. Can be a list of variants to choose randomly from: [variant1,variant2,variant3]
        # Variant files that use ships or weapons from third party mods that may or may not be installed can be put in [data\config\modFiles\magicBounty_variants\shipVariantId.variant] to avoid crashing on launch if said mods are absent. The bounty will need the proper mod requirements to be generated without issue.
        "fleet_flagship_name":"Flagship", # Default: Random.
        "fleet_flagship_recoverable": true, # Default: false. Whether the flagship will be always recoverable. Allowing this will still let the player fail the bounty if they were not supposed to recover the flagship.
        "fleet_flagship_autofit": false, # Default: false. Whether the flagship will be autofitted. When false, the Flagship does not receive D-mods or S-mods from the quality override.
		"fleet_preset_ships": { # Default: no presets. Preset fleet generated with the flagship. First value is the variant id, second is the number of them in the fleet.
            "ship_variant1":1,
            "ship_variant2":3,			
        },
        "fleet_preset_autofit": true, # Default: false. Whether the preset ships will be autofitted. When false, the preset ships do not receive D-mods or S-mods from the quality override.
        "fleet_scaling_multiplier": 1, # Default: no scaling. Dynamic reinforcements to match that amount of player fleet DP, set to 0 to ignore.
        "fleet_min_FP": 100, # Default: no minimum. Minimal total fleet size, set to -1 to ignore.
        "fleet_composition_faction": "pirates", # Default: bounty fleet faction. Used if the extra ships don't match the fleet's faction. For example a pirate fleet of Hegemony deserters. Required for min FP and player adjustment.
        "fleet_composition_quality": 1, # Default: 1, use 2 for no Dmods.
        "fleet_transponder": false, # Default: true.
		"fleet_no_retreat": false, # Default: false.
        "fleet_behavior": "PASSIVE", # Default:"GUARDED". The fleet's behavior on the campaign layer. Options: ["PASSIVE", "GUARDED", "AGGRESSIVE", "ROAMING"].

> fleet_faction : The faction of the fleet as encountered by the player, not necessarily the faction of origin for the officers and ships. MagicLib includes a generic "Bounty target" faction whose id is ML_bounty, that is neutral to everyone but the player. It can be used when spawning the target in a system filled with hostile fleets.

> fleet_flagship_variant : Sets the variant of the target flagship. This can be set as a list of variants to choose randomly from with ["variant1", "variant2", "variant3"]. If your variant uses weapons of hullmods from a different mod, it cannot be placed in the refgular variant folder otherwise the game will crash on startup when trying to load it. You can however place the variant file in data\config\modFiles\magicBounty_variants\, it will then only be loaded on demand without issue, if you setup your mod requirement properly that is. Additionally if your flagship has S-mods it must be loaded via this folder otherwise the ship won't keep those S-mods on recovery. Please note that the variant file name MUST match the variant ID.

> fleet_flagship_name : Overrides the flagship's random name. Be aware that it also overwrites the name prefix such as ISS or TTS, if you want to keep it, include it in the new name.

> fleet_flagship_recoverable : Garrantees at least a difficult recovery for the flagship. Especially usefull for bounties placed on unique ships, or with an otherwise low reward.

> fleet_preset_ships : Lists variants and their number that are generated along the flagship.

> fleet_flagship_autofit and fleet_preset_autofit : Enables the autofit on the flagship and the preset ships respectively. Note that this includes both modifying the loadout, but also adding D-mods or S-mods according to the fleet quality. Default to fasle as to prevent unexpected changes to the bounty fleet.

> fleet_scaling_multiplier and fleet_min_FP : These parameter define if and how much random reinforcement ships will be added to the bounty fleet. The min FP is the absolute minimum size of the fleet you want generated, including the values from the Flagship and the preset ships if any. Scaling refers to the proportion of extra FP that can be added, relative to the difference in size between the player fleet and the minimal target fleet size. For example, if the minimal size is 100 FP and the player fleet is 200 FP, a scaling of 0.5 would increase the bounty fleet size to a total of 100 + (200 - 100) * 0.5 = 150 FP. A scaling of 1 means the target fleet will always match the player fleet size.

> fleet_composition_faction and fleet_composition_quality : The composition faction represent the faction of the random ships added to the fleet, but also affects the random officers, the commander skills, and the weapons the flagship/preset ships can be reffited with. It default to the target faction if not defined. The quality affects the selection of weapons available for the loadouts, and the number of D-mods and S-mods the ships will get. A quality of 1 meanst 1 S-mod on average and between 0 and 1 D-mod. A quality of 2 means 2 S-mods on average and no D-mods.

> fleet_behavior : Determine the order given to the bounty fleet.

  • PASSIVE will orbit it's spawn point and not care about the player or other fleets.
  • GUARDED will move toward enemies close but will not pursue them.
  • AGGRESSIVE will pursue enemies that can be detected.
  • ROAMING will patrol the system.

Note that a ROAMING fleet won't stay near its spawn point, this can make it harder to find thus consider enabling their transponder to make them detectable from afar.

A not-so-special bounty will set fleet_name, fleet_faction, fleet_flagship_variant, and fleet_min_FP. Consider enabling fleet_flagship_recoverable for a nice extra reward.

LOCATION

"Where am I going?"

Unless very specifically set to an entity, the location of a bounty will be heavily randomized. This is in part due to the open-world nature of the game, but also its impredictable state due other mods such as Nexerelin or Adjusted Sector.

        "location_entitiesID": [  # Default: no preset. Preset locations to spawn the bounty fleet, can default to the preferences if those are defined and the location doesn't exists due to Nexerelin random mode.
            "location1",
            "location2",
        ],
        "location_marketFactions": [  # Default: no faction specified. Markets of specified faction for the fleet to spawn at. Adding a faction market supersedes all other parameters except location_id.
            "faction" 
        ],
        "location_distance": "CLOSE", # Default: no preference. How far from the center to spawn the bounty fleet. Options: "CORE", "CLOSE", "FAR" or just left empty to ignore.
        "location_themes": [ # Default: no preference. System themes that are valid to spawn the fleet at.
            "theme_core_unpopulated",
            "theme_core_populated",
            "theme_core",
            "theme_interesting",
            "theme_interesting_minor",	
            "theme_ruins",
            "theme_ruins_main",
            "theme_ruins_secondary",
            "theme_derelict",
            "theme_derelict_mothership",
            "theme_derelict_cryosleeper",
            "theme_derelict_survey_ship",
            "theme_derelict_probes",
            "theme_unsafe",
            "theme_remnant",
            "theme_remnant_main",
            "theme_remnant_secondary",
            "theme_remnant_no_fleets",
            "theme_remnant_destroyed",
            "theme_remnant_suppressed",
            "theme_remnant_resurgent",
            
            "procgen_no_theme", #not so special bounties should add this attribute
            "procgen_no_theme_pulsar_blackhole", #or this one
        ],
        "location_themes_blacklist": [ # Default: none. System themes to never spawn the fleet at.
            "theme_already_occupied", #Will avoid systems with "hostile" themes taken from a merged list between mods. Includes all Remnant, Plague-Bearer, OCI, Blade-Breaker systems 
            "theme_already_colonized", #Will explicitely exclude systems with active markets, kind of mandatory for pirate bounties given that faction colonize otherwise interesting systems with Nexerelin
            "theme_hidden", #Used by that one story system
			"no_pulsar_blackhole",
        ],
        "location_entities": [ # Default: PLANET + JUMP_POINT + STABLE_LOCATION. Possible entities to spawn the fleet around.
            "gate",
            "station",
            "wreck",
            "debris",
            "stable_location",
            "comm_relay",
            "nav_buoy",
            "sensor_array",
            "gas_giant",
            "planet",
            "jump_point",
        ],
        "location_prioritizeUnexplored": true, # Default: false. Will pick in priority systems that have not been visited by the player yet, but won't override the distance requirements.
        "location_defaultToAnyEntity": true, # Default: false. If true and no suitable entity is found in any systems with the required Theme and distance, a random entity will be picked instead. Otherwise the script will ignore the distance requirements.

> location_entitiesID : This list define specific tokens the bounty can spawn at. It will take priority over all other settings, but you may still want to define other fallback parameters in case those expected entities are not present in the sector, for example when using Nexerelin with Random Mode enabled.

> location_marketFactions : List factions whose markets the bounty can spawn at. This takes priority over the following settings but is superceeded by location_entitiesID . While it is an easy solution to ensure the target fleet will be in an appropriate system for its faction, it also often means other fleets will be present around it. Depending on the factions involved, this can lead to the bounty fleet being taken out before the player has a chance to fight it, make the target difficult to reach, or give it reinforcements in the form of other fleet joining the fight, or even battle-stations. Use this carefully, or pair it with a ROAMING order.

> location_distance : Sets the band of space where the bounty will spawn at. CORE means it will pick a system within one third of the longest axis of the sector from the center. CLOSE will pick a system between the first and second third of the longest axis from the center. FAR will pick a system in the the outermost third of the longest axis of the sector.

> location_themes and location_themes_blacklist : "themes" are tags placed on the systems during the sector's generation depending on the content that was generated in them. Custom ones can also be added by mods to their systems. Unless you are using an ID or a faction market, it is VERY IMPORTANT to select some themes for either or both these parameters, otherwise the bounty can spawn anywhere, including near a blackhole, in the middle of a remnant infestation, or in hidden system reserved for the story. In addition to the vanilla and modded themes, MagicLib includes a couple of special ones to better control where the fleet will show up.

  • procgen_no_theme and procgen_no_theme_pulsar_blackhole are only available for location_themes, and select systems that are randomly generated but contain little to nothing of interest. The latter will avoid blackholes and pulsar systems. These can be used to direct your bounty to the more deserted parts of the sector.
  • theme_already_occupied is a blacklist theme that is used as a shorthand to avoid most "hostile" themes. It covers a shared list from MagicLib's modSettings file, that by default includes all remnant themes, blade-breakers, OCI and plague-bearers systems.
  • theme_already_colonized is a blacklist theme that will avoid systems containing active markets.
  • no_pulsar_blackhole is a blacklist theme to avoid blackhole and pulsar systems, it is redudant if location_themes only contains procgen_no_theme_pulsar_blackhole.
  • theme_hidden is a vanilla theme used for story critical systems. If you have not set any location_themes, this should always be blacklisted unless you are specifically looking for that system, or only offer this bounty after the main quest completion.

Some vanilla themes are "global" and are applied along several other more precise ones. For example theme_derelict is present in all systems with narrower derelict themes such as theme_derelict_probes, theme_derelict_survey_ship, theme_derelict_mothership, and theme_derelict_cryosleeper. Beware to not blacklist a general theme when you are looking for one of the narrower ones.

> location_entities : Lists which types of entity your bounty can be found around. It will default to planet, jump_point and stable_location. Unless job_show_location is set to exact, entities other than planets and jump points will only offer very vague directions.

> location_prioritizeUnexplored : Will pick systems that fit the requirements that have never been visited before first. If all suitable systems in the range band have been visited, a random one will be selected instead.

> location_defaultToAnyEntity : Will default to any entity in a system with the appropriate themes if no required entity can be found. If kept false, the script will pick a different range band to try and find the required entity there.

A not-so-special bounty will define either a location_marketFactions, or select a location_distance and add all four outlined blacklist themes to location_themes_blacklist.

GOOD PRACTICES

  • Remove unused parameters and comments. Keeping the visual noise makes bounties harder to decypher and increases the risk of a typo sneaking in somewhere.
  • A lot of parameters are only used for specific purposes. A generic bounty can be very simple and will not need many.
  • If you want to quickly test your bounty without having to play the game to reach the appropriate relationship level or fleet size, you can enable bounty_board_test_mode in MagicLib\data\config\modSettings.json to ignore most requirements.
  • Having devmode enabled together with the debug console available using starsector-core\starsector.bat will offer a trove of messages indicating exactly what the script is doing and why. This is an invaluable tool to find issues with your bounty.
  • Need help? You can join the Magic Lab discord server!