|
| 1 | +--- |
| 2 | +title: Understanding and editing random missions |
| 3 | +--- |
| 4 | + |
| 5 | +## Difficulty |
| 6 | + |
| 7 | +A basic requirement and variable for random missions is the Difficulty. It is an arbitrary decimal number in a range of [0, 100] (meaning 0 and 100 are included). |
| 8 | + |
| 9 | +If needed the maximum difficulty can be adjusted by those offsets: |
| 10 | + |
| 11 | +``` |
| 12 | +content.dll, 1143D4, 100f = maximum value of misn difficulty ~adoxa |
| 13 | +content.dll, 1175F0, 100f = maximum value of DestroyMission difficulty (I think; it's part of the StateMachine) ~adoxa |
| 14 | +content.dll, 11B22C, 100f = maximum value of rank_diff and generated mission difficulty ~adoxa |
| 15 | +``` |
| 16 | +[Source, adoxa](https://the-starport.com/forums/topic/2636/higher-rank-missions/20) |
| 17 | + |
| 18 | + |
| 19 | +## Difficulty Calculation for Job Offers (`mBase.ini`) |
| 20 | + |
| 21 | +A key to understand how Difficulty works is the way how it is used and calculated. This is unfortunately not very easy to understand at first. |
| 22 | +The main use is within `mBase.ini` where the values are set which difficulty a player can get from a base or NPC. |
| 23 | + |
| 24 | +The difficulty number displayed in-game when reading a mission offer has a somewhat direct connection to the chosen technical difficulty behind. Apparently those in-game numbers are hard-coded somewhere for specific difficulty values. |
| 25 | + |
| 26 | +Commonly the `mission_type` parameter can be understood as: |
| 27 | +```ini |
| 28 | +mission_type = DestroyMission, <mindiff>, <maxdiff>, <chance> |
| 29 | +``` |
| 30 | + |
| 31 | +`minDiff` and `maxDiff` are important for the calculation of the real Difficulty that will be available for the player. Especially important is to note that **maxDiff is not necessarily the total maximum**. |
| 32 | +The calculations are as follows (in pseudo code): |
| 33 | +### Single Player |
| 34 | +```c |
| 35 | +// rank_diff = based on internal MissionNum and DATA\MISSIONS\rankdiff.ini |
| 36 | +// min_diff and max_diff are from mission_type/misn in DATA\MISSIONS\mbases.ini |
| 37 | +// 0 <= rnd < 1 |
| 38 | + |
| 39 | +factor = 1.3689^3 |
| 40 | + |
| 41 | +diff1 = rank_diff / factor |
| 42 | +if (diff1 < 0) |
| 43 | + diff1 = 0 |
| 44 | +if (diff1 > 100) |
| 45 | + diff1 = 100 |
| 46 | + |
| 47 | +diff2 = rank_diff * factor |
| 48 | +if (diff2 < 0) |
| 49 | + diff2 = 0 |
| 50 | +if (diff2 > 100) |
| 51 | + diff2 = 100 |
| 52 | + |
| 53 | +if (diff2 <= min_diff) |
| 54 | + return 0 // become a better pilot |
| 55 | + |
| 56 | +if (diff2 >= max_diff) |
| 57 | +{ |
| 58 | + d = max_diff / factor |
| 59 | + if (min_diff >= d) |
| 60 | + d = min_diff |
| 61 | + return max_diff - cos(rnd * pi/2) * (max_diff - d) // cos in RAD |
| 62 | +} |
| 63 | + |
| 64 | +if (diff1 < min_diff) |
| 65 | + diff1 = min_diff |
| 66 | + |
| 67 | +return max_diff - cos(rnd * pi/2) * (max_diff - diff1) // cos in RAD |
| 68 | +``` |
| 69 | +### Multi Player |
| 70 | +```c |
| 71 | +// min_diff and max_diff are from mission_type/misn in DATA\MISSIONS\mbases.ini |
| 72 | +// 0 <= rand < 3 |
| 73 | +// 0 <= rnd < 1 |
| 74 | + |
| 75 | +if (rand == 0) |
| 76 | +{ |
| 77 | + d = max_diff |
| 78 | +} |
| 79 | +else |
| 80 | +{ |
| 81 | + factor = 1.3689^(rand * 2 + 2) |
| 82 | + d = max_diff * factor |
| 83 | +} |
| 84 | +if (d < 0) |
| 85 | + d = 0 |
| 86 | +if (d > 100) |
| 87 | + d = 100 |
| 88 | + |
| 89 | +return d - cos(rnd * pi/2) * (d - min_diff) // cos in RAD |
| 90 | +``` |
| 91 | +[Source, adoxa](https://the-starport.com/forums/topic/2636/higher-rank-missions/7) |
| 92 | + |
| 93 | +Looking especially on the first part of the multiplayer-specific calculation shows that `maxDiff` *is not a total value*, but is getting multiplied by a randomized factor. This can make multiplayer missions of a max difficulty of greater than 8.1101 already reach a total 100 if the randomized numbers are highest. |
| 94 | + |
| 95 | +To understand the influence of the `minDiff` and `maxDiff` values in those calculations I do recommend to look on a graph plot for some simple values. |
| 96 | + |
| 97 | +To limit the difficulty in multiplayer exactly between the `minDiff` and `maxDiff` value, the following patch can be applied on `Content.dll` using [bwpatchw](http://adoxa.altervista.org/misc/dl.php?f=bwpatch-w). |
| 98 | +```sh |
| 99 | +# Make MP job difficulty exactly between min and max difficulty in mbases.ini. |
| 100 | +# Jason Hood (adoxa), 22 February, 2010. |
| 101 | +# Fixed 3 June, 2010. |
| 102 | + |
| 103 | +File: content.dll # v1.1 |
| 104 | +0AAD7A: 89 44 E4 04 D9 44 E4 20 D8 64 E4 [ 99 B9 03 00 00 00 F7 F9 85 D2 74 ] |
| 105 | +1C EB 04 66 B8 FB 06 DB 44 E4 04 [ 33 D9 05 30 B2 FB 06 DD 5C 24 04 ] |
| 106 | +D8 0D D0 97 39 06 DE C9 D8 44 E4 [ FF D6 99 DD 44 24 04 B9 03 00 00 ] |
| 107 | +1C 5E 83 C4 10 C3 [ 00 F7 F9 8D 54 12 ] |
| 108 | +``` |
| 109 | +[Source, adoxa](https://the-starport.com/forums/topic/2636/higher-rank-missions/10) |
| 110 | + |
| 111 | +## Amount of NPCs created by Difficulty and NPC Level (`npcranktodiff.ini`) |
| 112 | + |
| 113 | +It is possible to define exactly how many NPCs of a specific level are being created for a specific Difficulty. This is handled within the `npcranktodiff.ini`. |
| 114 | + |
| 115 | +A line looks as follows: |
| 116 | +```ini |
| 117 | +NpcRank = <npc level>, <difficulty for 1 ship>, <difficulty for 2 ships>, <difficulty for 3 ships>, … |
| 118 | +``` |
| 119 | +Important to note: |
| 120 | +- Only exactly one line of `NpcRank` is picked for the spawn per wave in a job. |
| 121 | +- The amount of spawned ships is determined by the highest Difficulty in that line (e.g. if Difficulty is 5 and the 3rd ship column is 5, then 3 ships get spawned). |
| 122 | +- By default the game can handle up to 8 ships per line. To allow for more, see the following. |
| 123 | + |
| 124 | +The game uses a table of weights to define a preference for the amount of ships being spawned. It is as follows: |
| 125 | +|Ships|SP|MP| |
| 126 | +|-----|--|--| |
| 127 | +|1 |0 |0 | |
| 128 | +|2 |3 |2 | |
| 129 | +|3 |9 |3 | |
| 130 | +|4 |6 |9 | |
| 131 | +|5 |2 |6 | |
| 132 | +|6 |1 |4 | |
| 133 | +|7 |1 |2 | |
| 134 | +|8 |1 |1 | |
| 135 | + |
| 136 | +[Source, adoxa](https://the-starport.com/forums/topic/2636/higher-rank-missions/22) |
| 137 | + |
| 138 | +The weights here are again relative to their sum. E.g. in multiplayer the sum is 27, so 4 ships get spawned in 9 out of 27 cases (33.3%). As you can see, 1 ship has weight of 0. This means the game never will pick an `NpcRank` where the Difficulty for only the first ship would match. |
| 139 | +This table is very important to keep in mind. At any Difficulty picked, there always should be `NpcRank`s defined that cover all those ship counts. |
| 140 | +If you notice your job-board being more empty than it should be, it could be that the game tries to pick a ship count which is not provided for the current Difficulty. |
| 141 | + |
| 142 | +This table can be adjusted at the offset `11CC58` in `Content.dll`. First are the weights for singleplayer (starting for 0 ships, 1 ship, 2 ships, etc.) and after that for multiplayer (also starting for 0 ships, 1 ship, …). |
| 143 | + |
| 144 | +If you want to allow `NpcRank`s with more than 8 ships being spawned, you must create your own weight-table. |
| 145 | +``` |
| 146 | +content.dll 0F8A4B 58CCFB->00CBFC = use 30-float array at 12CB08 (created manually!) for SP ship weighting vector ~adoxa |
| 147 | +content.dll 0F8A54 7CCCFB->80CBFC = use 30-float array at 12CB88 (created manually!) for MP ship weighting vector ~adoxa |
| 148 | +``` |
| 149 | +[Source, adoxa](https://the-starport.com/forums/topic/2636/higher-rank-missions/22) |
| 150 | + |
| 151 | +## Requirements to have Missions offered on a Base |
| 152 | + |
| 153 | +There are 4 requirements that must be met to have a mission of a specific Difficulty being offered to a player: |
| 154 | +- The enemy faction must have an NPC spawn of any unrelated `level`/`difficulty` within at least one mission vignette zone in the system. |
| 155 | +- The enemy faction must have at least one `NpcShip` from `npcships.ini` assigned via `faction_prop.ini` that must have the **same** `level` as any Difficulty-matching `NpcRank`, and have `npc_class` `class_fighter`. |
| 156 | +- The enemy faction must have at least one `NpcShip` from `npcships.ini` assigned via `faction_prop.ini` that must have the **matching** `npc_class` `diff`-label + `class_fighter` for the matching `NpcRank`. And this `NpcShip` must have a `level` matching ±1. |
| 157 | +- There must be at least one `NpcRank` that can spawn ships within the picked Difficulty range. |
| 158 | + |
| 159 | +This sounds quite daunting, so let’s explain this on an example: |
| 160 | + |
| 161 | +We want to have some faction offer missions against `fc_lr_grp` in our system. For this we at first need a mission zone: |
| 162 | +```ini |
| 163 | +[Zone] |
| 164 | +nickname = Zone_destroy_vignette_01 |
| 165 | +pos = 0, 0, 0 |
| 166 | +shape = SPHERE |
| 167 | +size = 10000 |
| 168 | +mission_type = unlawful, lawful |
| 169 | +vignette_type = open |
| 170 | +``` |
| 171 | +Now we must make sure the enemy spawns within this zone, so it will get selected by the game to be associated with this enemy faction. |
| 172 | +```ini |
| 173 | +[Zone] |
| 174 | +nickname = Zone_destroy_vignette_01_pop |
| 175 | +pos = 0, 0, 0 |
| 176 | +shape = SPHERE |
| 177 | +size = 100000 |
| 178 | +toughness = 19 |
| 179 | +density = 1 |
| 180 | +repop_time = 25 |
| 181 | +max_battle_size = 4 |
| 182 | +relief_time = 35 |
| 183 | +encounter = area_scout, 1, 1 |
| 184 | +faction = fc_lr_grp, 1 |
| 185 | +``` |
| 186 | +Now we must find out which Difficulty our mission may have. For this we check in our `mBase.ini`: |
| 187 | +```ini |
| 188 | +mission_type = DestroyMission, 0, 0.112387, 100 |
| 189 | +``` |
| 190 | +With this value we now go into our `npcranktodiff.ini` file and look which line might match. Keep in mind the game has certain weights on how many ships it prefers to spawn (see above chapter). One of the possible `NpcRank`s might be: |
| 191 | +```ini |
| 192 | +NpcRank = 1, 0.00985, 0.03569, 0.07754, 0.13539, 0.20923, 0.29908, 0.40493, 0.52677 |
| 193 | +``` |
| 194 | +With this we know that we want to spawn level 1 NPCs. |
| 195 | +Now we must make sure `fc_lr_grp` has at least one ship matching this with an `npc_class` of `class_fighter`: |
| 196 | +```ini |
| 197 | +[NPCShipArch] |
| 198 | +nickname = fc_lr_pi_fighter_d1 |
| 199 | +loadout = fc_lr_pi_fighter_loadout01 |
| 200 | +level = d1 |
| 201 | +ship_archetype = pi_fighter |
| 202 | +pilot = pilot_pirate_med |
| 203 | +state_graph = FIGHTER |
| 204 | +npc_class = unlawful, class_fighter, d1 |
| 205 | +``` |
| 206 | +We see that the `level=d1`, matching our `NpcRank`. And we see the `npc_class` contains `d1` and `class_fighter`, so it also can spawn the ship. |
| 207 | +Important to know is that one ship with the required level must exist. But it does not need to be the same ship that is being spawned! |
| 208 | +The ships that will be spawned are determined by their matching `npc_class` label. Meaning that if your ship has `d1`, but `npc_class` `d100`, it will not be spawned. |
| 209 | +You can and must have at least one (but it can be another) ship with a matching `npc_class` `diff`-label for `d1`, and `class_fighter`. Important here is that whatever ship has the matching `npc_class` must match the `level` +1. |
| 210 | +So we could say we have a `level` `d2` ship with `npc_class=diff1`, `class_fighter`, it would be able to be spawned. But only if there is another ship defined somewhere that has `level=d1`. This may look like this and still get spawned in our `d1` mission: |
| 211 | +```ini |
| 212 | +[NPCShipArch] |
| 213 | +nickname = fc_lr_pi_fighter_d1-d2 |
| 214 | +loadout = fc_lr_pi_fighter_loadout01 |
| 215 | +level = d2 |
| 216 | +ship_archetype = pi_fighter |
| 217 | +pilot = pilot_pirate_med |
| 218 | +state_graph = FIGHTER |
| 219 | +npc_class = unlawful, class_fighter, d1, d2 |
| 220 | +``` |
| 221 | + |
| 222 | +## Payment by Difficulty (`diff2money.ini`) |
| 223 | + |
| 224 | +Defining payments for specific Difficulties is very easy and straight-forward to be done in `diff2money.ini`. |
| 225 | +A line looks as follows: |
| 226 | +```ini |
| 227 | +Diff2Money = <start difficulty>, <payment> |
| 228 | +``` |
| 229 | +You can add as many or as few of those lines as you like. The payments between each defined Difficulty are linearly interpolated. You should at least provide a line for Difficulty 0 and 100 to allow the game to compute any payments between. |
0 commit comments