Fractal Softworks Forum

Please login or register.

Login with username, password and session length

Author Topic: (WIP) Tutorial: Editing Spawned Fleet Distribution using Faction Files (0.7.2a)  (Read 4631 times)

Morrokain

  • Admiral
  • *****
  • Posts: 2143
  • Megalith Dreadnought - Archean Order
    • View Profile

So this is meant to be pretty straightforward. Since a cursory glance hasn't revealed any posts on this topic, I would like to get the info out there on how to spawn your own custom fleets with help from the modding community and Alex, if possible.

IMPORTANT STUFF
From here on out, I am posting what I think this code does based upon my own personal play testing. I am making this post in the hopes that other members of the modding and development community can contribute to the accuracy of this post for the betterment of the community as a whole.

WHERE:
Specifically I want to focus on fleet distribution using the faction files located in starsector/starsector-core/data/world/factions directory to spawn custom fleets in place of the core game fleets.


OPENING THE FILE:

Open one of these files in a text editor. I use notepad but notepad++ I have heard is better at color coding syntax and a variety of other convenience things.

A First Look at Spawn Probability:

Open a factions file (I am using the Hegemony file as the example in this post) and scroll down to the the portion marked "doctrine". It is located near the bottom of the file and should appear similar to this:

Code
	"doctrine":{
# ship distribution
"interceptors":4,
"fighters":6,
"bombers":2,
"small":8,
"fast":4,
"medium":12,
"large":6,
"capital":3,

# as fraction of combat ships of same size
"escortSmallFraction":1,
"escortMediumFraction":1,

"combatFreighterProbability":0.1,

"minPointsForCombatCapital":10,
"minPointsForLargeCarrier":30,

"smallCarrierProbability":0.25,
"mediumCarrierProbability":0.25,
"largeCarrierProbability":0.25,

The first section of the code is ship distribution. This section determines what type and how many of each ship type will spawn when a new fleet is generated.

The portion in quotes (i.e: "small":8,) is an ID for a ship type that is further defined by one or several ship variant file IDs earlier in the Factions file. Do not worry about that for now, we will get to that later on in this post. Just understand that each ID represents a grouping of ship variants you can define yourself.

The second part of code after the ":", the number (i.e: "small":8,), is the probability weight given to this grouping. This means that when each fleet is generated in the game the higher the number given to the "small" ship type the more likely "small" type ships will be spawned.

IMPORTANT NOTE ON PROBABILITY WEIGHTS:

It is important to note that probability weight is different from a set scale weight or ratio. Weights of 2 and 4  for the ship types frigate and fighter respectively will not equal 2 frigates and 4 fighters every time (or even most of the time in my experience  ::) ). It is still very likely fleets will spawn all frigates or 5 frigates and a single fighter with such low weight variance.

It is also important to note here that a "higher" number only means one higher relative to the other ship grouping weights defined under the ship distribution section. So for example say "small" is given a weight of 8, "fighter" is given a weight of 16 and "capital" is given a weight of 4. In this case "fighter" type ships will spawn roughly 2 times more often than "small" type ships and roughly 4 times more often than "capital" type ships. However, the same cannot be said if the weights were 8 for "small", 16 for "fighter", and 2 for "capital". Then, though "fighter" type ships would still spawn roughly 2 times more often than "small" type ships, they would now spawn roughly 8 times more often than "capital" type ships. Simply making the number higher will not spawn more ships by itself unless the other ships all remain the same.

So if you want more "set" fleets, using higher weight variance helps, but of course cannot outright eliminate, situations where fleets are composed of more or less of one ship type than intended.

MOVING ON TO MULTI LEVEL PROBABILITY IN STARSECTOR:

In Starsector, there are a couple different probability levels for each type of fleet spawned. Freighter fleets, for example, have the freighters themselves in small, medium and large types, but also have a percentage chance to spawn combat freighters of the same size instead of freighters for each ship spawned. Along the same lines, any combat ship has a ratio to express the number of "escort" type ships of each size that will be spawned instead of the normal combat vessels defined earlier in the file. These two layers of probability are determined in the next section of code after fleet distribution :

Code
		# as fraction of combat ships of same size
"escortSmallFraction":1,
"escortMediumFraction":1,

"combatFreighterProbability":0.1,

So in this example for every 2 "small" and "medium" ship type spawned, one will be an escort with a 1:1 ratio. This is a "hard" ratio I believe (one of the few in the game) so not exactly a probability but nonetheless another layer to manage in fleet distribution.

Similarly, in this example combat freighters will spawn roughly 1 out of every 10 times a freighter spawns (10% chance = 0.1). This is not a "hard" ratio but probability like the rest of the weights we have been dealing with so far.

CARRIERS, AN EXCEPTION TO THE RULE:

Carrier probability works slightly differently. The next section of code looks like this:

Code
		"minPointsForCombatCapital":10,
"minPointsForLargeCarrier":30,

"smallCarrierProbability":0.25,
"mediumCarrierProbability":0.25,
"largeCarrierProbability":0.25,

** this section needs to be worked on**

The first two lines are unclear to me. I am not sure what "points" are being referred to here, but the idea is the higher the number the less access to larger ships. It does not seem to be fleet points because in my current W.I.P mod capitals never spawn for some reason even with it set to 10 and many fleets have far more than 10 fleet points in their composition.

** this section needs to be worked on**

The last 3 lines, however, set the probability a carrier will spawn once in a fleet. As far as I can tell, a probability of 1.0 (100%) means that a single carrier of the designated size will be included in combat fleets and patrols. They do not seem to have any effect on freighter convoys. If multiple sizes are set to 1.0 then both carriers will be included in the fleet if it is large enough. (patrol or higher)

Also, any fleet that includes a carrier will have a couple more fighter, interceptor or bomber wings added seemingly at random regardless of the weights set earlier under ship distribution.


VARIANT IDs, VARIANT WEIGHTS AND SHIP TYPE GROUPINGS:


Now that we understand how the different layers of probability operate outside of the ship type groupings, lets take a look at how each of these layers works together alongside individual grouping weights to add yet another layer of probability to ship composition.

Each ship type grouping has a number of variant IDs assigned to it earlier in the factions file. Scroll up to find the code Ship Roles:

Code
	"shipRoles":{
"interceptor":{
"talon_wing":10,
"thunder_wing":10,
"fallback":{"fighter":1},
},
"fighter":{
"broadsword_wing":10,
"gladius_wing":10,
"warthog_wing":10,
"fallback":{"interceptor":1},
},
"bomber":{
"piranha_wing":10,
},

"fastAttack":{
"lasher_Standard":5,
"lasher_Strike":5,
"hound_hegemony_Standard":10,
"wolf_hegemony_Assault":2,
"fallback":{"combatSmall":1},
},

"escortSmall":{
"lasher_CS":10,
"lasher_PD":10,
"monitor_Escort":2,
"wolf_hegemony_PD":10,
"vigilance_FS":10,
"kite_Interceptor":5,
"fallback":{"combatSmall":1},
},
"escortMedium":{
"enforcer_Escort":10,
"enforcer_Balanced":10,
"enforcer_Outdated":10,
"enforcer_CS":10,
"hammerhead_Balanced":10,
"enforcer_Elite":10,
"enforcer_XIV_Elite":4,
"hammerhead_Elite":10,
"fallback":{"combatMedium":1},
},

"combatSmall":{
"wolf_hegemony_CS":10,
"lasher_Standard":5,
"lasher_Strike":5,
"lasher_CS":5,
"lasher_Assault":5,
"vigilance_Standard":10,
"vigilance_FS":10,
"vigilance_Strike":10,
"brawler_Assault":10,
"centurion_Assault":10,
"fallback":{"escortSmall":1},
},
"combatMedium":{
"enforcer_Assault":10,
"enforcer_Balanced":10,
"enforcer_Outdated":10,
"enforcer_CS":10,
"enforcer_XIV_Elite":8,
"hammerhead_Balanced":10,
"sunder_CS":10,
"hammerhead_Elite":10,
"enforcer_Elite":10,
"sunder_Assault":10,
"fallback":{"combatSmall":2},
},
"combatLarge":{
"falcon_Attack":10,
"falcon_CS":10,
"falcon_xiv_Elite":3,
"falcon_xiv_Escort":4,
"eagle_Assault":10,
"eagle_Balanced":10,
"eagle_xiv_Elite":5,
"dominator_Support":6,
"dominator_Assault":6,
"dominator_AntiCV":6,
"dominator_Outdated":6,
"dominator_XIV_Elite":5,
"gryphon_Standard":10,
"gryphon_FS":5,
"fallback":{"combatMedium":2},
},
"combatCapital":{
"onslaught_Standard":10,
"onslaught_Outdated":10,
"onslaught_Elite":10,
"onslaught_xiv_Elite":3,
"fallback":{"combatLarge":2},
},


# hybrid ships with good combat and cargo capacity
"combatFreighterSmall":{
"hound_hegemony_Standard":10,
"shepherd_Frontier":10,
"cerberus_Standard":4,
"cerberus_Hardened":4,
"cerberus_Shielded":4,
"wayfarer_Standard":10,
"fallback":{"freighterSmall":1},
},
"combatFreighterMedium":{
"mule_d_Standard":10,
"mule_Standard":10,
"fallback":{"combatFreighterSmall":2},
},
"combatFreighterLarge":{
"venture_Balanced":10,
"fallback":{"combatFreighterMedium":2},
},

"civilianRandom":{
"mercury_d_Standard":10,
"hermes_d_Standard":10,
"mercury_Standard":8,
"mercury_FS":3,
"hermes_Standard":10,
"starliner_Standard":10,
"nebula_Standard":10,
"mudskipper_Standard":10,
"kite_Interceptor":5,
"kite_Standard":5,
"fallback":{"freighterSmall":1},
},

# carriers
"carrierSmall":{
"condor_FS":5,
"condor_Support":5,
"gemini_Standard":10,
"fallback":{"carrierMedium":0.5},
},
"carrierMedium":{
"heron_Standard":10,
"fallback":{"carrierSmall":2},
},
"carrierLarge":{
"fallback":{"carrierMedium":2},
},

# freighters and such
"freighterSmall":{
"hermes_d_Standard":10,
"hermes_Standard":10,
"fallback":{"freighterMedium":0.5},
},
"freighterMedium":{
"tarsus_d_Standard":5,
"buffalo_d_Standard":5,
"buffalo_Standard":10,
"tarsus_Standard":10,
"buffalo_hegemony_Standard":10,
"fallback":{"freighterSmall":2},
},
"freighterLarge":{
"atlas_Standard":10,
"fallback":{"freighterMedium":2},
},

"tankerSmall":{
"dram_Light":10,
"fallback":{"tankerMedium":0.5},
},
"tankerMedium":{
"phaeton_Standard":10,
"fallback":{"tankerSmall":2},
},
"tankerLarge":{
"prometheus_Super":10,
"fallback":{"tankerMedium":2},
},

"personnelSmall":{
"mercury_d_Standard":10,
"mercury_Standard":10,
"mudskipper_Standard":2,
"kite_Interceptor":5,
"fallback":{"personnelMedium":0.5},
},
"personnelMedium":{
"valkyrie_Elite":10,
"nebula_Standard":1,
"fallback":{"personnelSmall":2},
},
"personnelLarge":{
"fallback":{"personnelMedium":3},
},

# utility ships
"tug":{
"ox_Standard":10,
"fallback":{"utility":1},
},
"crig":{
"crig_Standard":10,
"fallback":{"utility":1},
},
"utility":{
"crig_Standard":10,
"ox_Standard":10,
},

As you can probably see, each grouping is labeled in quotes and the variant IDs are and their individual weights are included in the "{}" brackets. In our earlier example. "small" equals "combatSmall" and that grouping includes these variants:

Code
		"wolf_hegemony_CS":10,
"lasher_Standard":5,
"lasher_Strike":5,
"lasher_CS":5,
"lasher_Assault":5,
"vigilance_Standard":10,
"vigilance_FS":10,
"vigilance_Strike":10,
"brawler_Assault":10,
"centurion_Assault":10,

Each variant has a number assigning its weight just like before, and these weights are taken into account after the higher level weights are determined in the generated fleet. So once the fleet generator has determined that a small ship type will be spawned and it will not be an "escort" type ship, it chooses from the variant IDs based upon their own weights and adds that ship to the fleet.

So to summarize, for every time a small, non-escort, combat ship spawns in the fleet composition (higher level layers of probability), it will be twice as likely that it will select a variant ID with a weight of 10 over a weight of 5 (lower level layer of probability).


WHAT IS NOT CLEAR:

SO now for the things I do not know or even have much of a guess on at this point:

1) How does the fleet generator select different groupings for each fleet label? So for example, a "Detachment" fleet is the only fleet that seems to use the "large" or "capital" ship weight. Patrols only can use the "mediumCarrier" type, it will exclusively use the large carrier in detachments. All fleets seem to use the combat freighter probability for any potential freighter spawned yet carriers are never included in freighter fleets. Escorts are even less clear. They sometimes seem to spawn in freighter convoys, sometimes not. Fast picket fleets seems to always exclusively use the "fast" type and ignores all others, but other fleets sometimes use "fast" ships as well, but at random.

The real confusion here is how fighters, bombers and interceptors are chosen. It seems completely irregardless of the weight they are assigned in that increasing the variance of the weights only affects the fleets in which they are spawned at all. The fleets that choose to field them are unclear. As I have said earlier carriers always seem to have a couple extra, and heavier patrols and detachments use the weights seemingly only sometimes. If you want a fighter heavy faction, my recommendation at this point is to include fighters in the "fast" and "smallEscort" grouping at a high weight variance. Even then, it is certainly not a guarantee that there will be some in every fleet and others will sometimes have far too many.

2) How can you determine how many ships are spawned per fleet? This option is not present in the faction file or seemingly in any of the other scripts.


Thanks for reading!!
« Last Edit: May 18, 2016, 01:31:11 PM by Morrokain »
Logged

SafariJohn

  • Admiral
  • *****
  • Posts: 3020
    • View Profile

Most of the fleet spawning stuff is handled in the FleetFactory.class and other .class files in the campaign.fleets package of the starfarer.api.jar; I've never given it more than a casual glance through so I'm not familiar with exactly how it works.

The point value for a ship when building a fleet is the "fleet pts" column in ship_data.csv, IIRC.
Logged

Morrokain

  • Admiral
  • *****
  • Posts: 2143
  • Megalith Dreadnought - Archean Order
    • View Profile

Most of the fleet spawning stuff is handled in the FleetFactory.class and other .class files in the campaign.fleets package of the starfarer.api.jar; I've never given it more than a casual glance through so I'm not familiar with exactly how it works.

The point value for a ship when building a fleet is the "fleet pts" column in ship_data.csv, IIRC.

Thanks for the info Hartlord! I will do an edit to incorporate that soon.

A little disappointed to have to break into the jar file to truly understand fleet composition when the last system was so easy in comparison (simple text editing), but I certainly understand the long term appeal of the procedural randomness that this new method provides.
Logged

Histidine

  • Admiral
  • *****
  • Posts: 4681
    • View Profile
    • GitHub profile

Don't open starfarer.api.jar if you're doing that; extract starfarer.api.zip and read the .java source files directly.
Logged

Dark.Revenant

  • Admiral
  • *****
  • Posts: 2806
    • View Profile
    • Sc2Mafia

I basically co-wrote this system, so here's how all that stuff works:

When a fleet is spawned, a FleetParams object is passed in.  The pertinent fields of that are:
Code
	public float combatPts; 	
public float freighterPts;
public float tankerPts;
public float transportPts;
public float linerPts;
public float civilianPts;
public float utilityPts;

Each of these does what you might expect.  Side note: "Points" are 1/2/4/8 for frigates/destroyers/cruisers/capital ships.  Here are some common fleet types:

Small/Fast Patrol
combatPts: 3 - 15 (average 7.5)

Medium/Combat Patrol
combatPts: 6 - 36 (average 14.5)
tankerPts: 0 - 1

Large/Heavy Patrol
combatPts: 10 - 60 (average 23)
tankerPts: 2
freighterPts: 2

Pirate Armada
combatPts: 12 - 20

Luddic Path
combatPts: 1 - 4

Tier 10 Trade Fleet (~88+ % of max trade volume)
combatPts: 10 - 15
freighter/tanker/transportPts: collectively 20 - 30
utilityPts: 1


Freighters (and combat freighters) work roughly as you describe.  However, combat points work differently.  Everything is divided into "groups" of 16 points, or 12 if there isn't enough room, then 8 if there isn't enough room, and finally the remainder is dumped into random ships.  The 16/12/8-point groups have a chance of being a large/medium/small carrier group, according to the "*CarrierProbability" fields in the doctrine.  Therefore, if you use "1" for all the probabilities, the fleet will always spawn a consistent carrier force; 0 for all the probabilities will cause the fleet to spawn no carriers at all.

A carrier group contains a carrier and some fighters, and potentially some small combat vessels.  An 8-point carrier group usually has a destroyer-sized carrier, 3 wings of fighters, and 3 points of random combat vessels.  A 12-point carrier group usually has a cruiser-sized carrier (but sometimes 2 destroyer-sized carriers), 5 wings of fighters, and 3 points of random combat vessels.  A 16-point carrier group usually has a capital-sized carrier (though sometimes 2 cruiser carriers, or 1 cruiser carrier and 2 destroyer carriers), and 8 wings of fighters.  Non-carrier groups just translate directly to random combat vessels.

So, for example, a 24-point fleet would, in an ideal scenario, have a 16-point group and an 8-point group, meaning it can be 24 points of combat ships; or potentially 10 points of carriers, 11 wings of fighters, and 3 points of combat ships.  In reality, the groups can be fudged up or down (usually up) depending on circumstance; you could potentially have a 16-point group end up taking more like 20 points if the dice fall that way when picking random ships.  The total amount of points gotten from the fleet won't exceed the overall limit, however; a 24-point fleet can have up to, but no more than, 24 points of ships.

By the way, the "minPointsForCombatCapital" and "minPointsForLargeCarrier" fields just mean that there must be X combatPts in the FleetParams, otherwise capital ships of the combat / carrier variety won't spawn.


Weights for picking ships are not exactly as they appear in the doctrine, because the picking algorithm is biased towards smaller ships (since they use fewer points).  Once 22 points of ships are picked in a 24-point fleet, the last two points can only ever be COMBAT_SMALL or FAST_ATTACK.  This is probably why you saw small patrols using lots of FAST_ATTACK ships. This bias is generally weaker as the fleet size increases, as the threshold for this bias is the 9-point mark; a 24-point fleet would have 63% of those points using linear odds, while a 60-point fleet would have 85% of its points using linear odds.  Note that this only applies for "random combat ships".  Bombers are biased against; other types of fighters will be more common from random rolls (this doesn't apply for carrier groups, however).

1 - 2 combatPts: COMBAT_SMALL and FAST_ATTACK only
3 combatPts: Fighters appear
4 - 6 combatPts: COMBAT_MEDIUM and ESCORT_SMALL appear
7 - 9 combatPts: COMBAT_LARGE and ESCORT_MEDIUM appear
10+ combatPts: COMBAT_CAPITAL appears (all combat ships are allowed)
Logged

Morrokain

  • Admiral
  • *****
  • Posts: 2143
  • Megalith Dreadnought - Archean Order
    • View Profile

Wow! Thanks Dark.Revenant things make so much more sense now lol. I was really struggling to determine the method behind the madness there and without going into the jar file things are definitely not obvious but with this modders who can't or don't want to deal with that at least know how to manipulate the fleet composition effectively. ;D Do you mind if I reincorporate that information and correct the original post? You will be credited of course!
Logged