Skip to content

Commit 6ff6e6b

Browse files
committed
Add Random Missions Editing Tutorial
1 parent b66e785 commit 6ff6e6b

File tree

2 files changed

+231
-1
lines changed

2 files changed

+231
-1
lines changed

docs/guides/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ id: guides
66
This page contains a list of written guides and processes for running, modding and troubleshooting Freelancer and FLServer.
77

88
* [Running multiple freelancer clients on a single machine](./multiple-clients-on-same-machine.md)
9-
9+
* [Understanding and adding infocards](./understanding-and-adding-infocards.md)
10+
* [Understanding and editing random missions](./random-missions-editing-tutorial.md)
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
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

Comments
 (0)