Frequently Asked Questions
Adding stuff
Adding a monster
- Edit
data/json/monsters.json
or create a new json file and insert the definition of your new monster there (probably copy an existing entry). - Make sure the id value is unique among all other monster types.
- Your monster type is now valid, but won’t be spawned. If you want it to be spawned among similar
monsters, edit monstergroups.json. Find the appropriate array, and insert the identifier for your
monster (e.g,
mon_zombie
).cost_multiplier
, makes it more expensive to spawn. The higher the cost, the more ‘slots’ it takes up, and freq is how frequent they spawn. Seemongroupdef.cpp
- If you want your monster to drop items, edit
monster_drops.json
. Make a new array for your monster type with all the map item groups it may carry, and a chance value for each. - Your monster may have a special attack, a
monattack::function
reference. Editmonattack.h
and include the function in the class definition; editmonstergenerator.cpp
and add the translation, then editmonattack.cpp
and define your function. Functions may be shared among different monster types. Be aware that the function should contain a statement that the monster uses to decide whether or not to use the attack, and if they do, should reset the monster’s attack timer. - Just like attacks, some monsters may have a special function called when they die. This works the
same as attacks, but the relevant files are
mondeath.h
andmondeath.cpp
. - If you add flags, document them in
JSON_FLAGS.md
, andmtype.h
. Please. Or we will replace your blood with acid in the night.
Adding structures to the map
Most “regular” buildings are spawned in cities (large clusters of buildings which are located rather close to each other).
In file omdata.h
in the enum oter_id
structure define names (code identifiers) for your
building.
If you want your building to be displayed at overmap in different orientations, you should add 4
identifiers for each orientation (south
, east
, west
and north
correspondingly).
In the same file in structure const oter_t oterlist[num_ter_types]
we should define how these
buildings will be displayed, how much they obscure vision and which extras set they have. For
example:
{"mil. surplus", '^', c_white, 5, build_extras, false, false},
{"mil. surplus", '>', c_white, 5, build_extras, false, false},
{"mil. surplus", 'v', c_white, 5, build_extras, false, false},
{"mil. surplus", '<', c_white, 5, build_extras, false, false}
Comments at the beginning of this structure are rather useful. In the file mapgen.cpp
find the
subroutine called draw_map(...);
where you should find a huge variant operator (“switch”). This is
where you should put your code defining the new building by adding new case-statement.
It should be mentioned that most buildings are built on the square SEEX*2 x SEEY*2
tiles.
If you want your building to be spawned not only in city limits you should refer to structures in
file omdata.h
(starting from the line #define OMSPEC_FREQ 7
).
These structures are also commented in source code. Add new identifier in enum omspec_id
structure
before NUM_OMSPECS
and then add a record in const overmap_special overmap_specials[NUM_OMSPECS]
array. For example:
{ot_toxic_dump, 0, 5, 15, -1, mcat_null, 0, 0, 0, 0, &omspec_place::wilderness,0}
The comments given in source code to structure struct overmap_special
explain the meaning of these
constants in the example above.
Adding a bionic
- Edit
data/json/bionics.json
and add your bionic near similar types. SeeJSON_INFO.md
for a more in-depth review of the individual fields. - If you want the bionic to be available in the game world as an item, add it to
item_groups.json
, and add a bionic item todata/json/items/bionics.json
. - Manually code in effects into the appropriate files, for activated bionics edit the
player::activate_bionic
function inbionics.cpp
. - For bionic ranged weapons add the bionic weapon counterparts to
ranged.json
, give them theBIONIC_WEAPON
flags. - For bionic close combat weapons add the bionic weapon to
data/json/items/melee.json
give themNON_STUCK
,NO_UNWIELD
at least.
How armor protection is calculated
- When the player is hit at a specific body part, armor coverage determines whether the armor is
hit, or an uncovered part of the player is hit (roll
1d100
against coverage). - If the above roll fails (ie roll value is above coverage), then the armor does not absorb any damage from the blow, neither does it become damaged.
- If the above roll succeeds, the armor is hit, possibly absorbing some damage and possibly getting damaged in the process.
- The above steps are repeated for each layer of armor on the body part.
- Armor protects against bash and cut damage. These are determined by multiplying the armor
thickness by the material bash/cut resistance factor respectively, given in
materials.json
. - If the armor is made from 2 materials types, then it takes a weighted average of the primary
material (
66%
) and secondary material (33%
). - Materials resistance factors are given relative to
PAPER
as a material (this probably needs some fine-tuning for balance).
Adding an iuse function.
- Add the new item use code to
iuse.cpp
andiuse.h
. - Add the new json_flag to your item. And link it to the iuse function in
item_factory.cpp
. - Document the new flag in
JSON_FLAGS.md
.
Acid resistance
This determines how items react to acid fields. Item acid resistances are a weighted average of the
materials acid resistance (see item::acid_resist
):
- An item acid resistance of zero means it will get corroded every turn;
- An item acid resistance above zero means it has a chance of getting corroded every turn;
- An item acid resistance above 9 means completely acidproof.
Acid resistance values are in materials.json
, and defined as such:
- 0 - zero resistance to acid (metals)
- 1 - partly resistant to acid
- 2 - very resistant to acid
- 3 - complete acid resistance
FAQ
Q: How do I prevent an item from showing up in NPC inventory?
A: Add the TRADER_AVOID
flag to it.
Q: What the heck is up with the map objects?
A: The pertinent map objects are submap, mapbuffer, map, and overmap. The submap contains the actual
map data, in SEEXxSEEY chunks. Vehicles and spawns are stored in vectors because they are relatively
sparse. Submaps live in the single global mapbuffer, MAPBUFFER. Map encapsulates the area around the
player that is currently active. It contains an array of MAPSIZE * MAPSIZE submap pointers called
grid. This is a 2D array, but is mapped to a 1D array for (questionable) indexing purposes. When the
player moves from one submap to another, map::shift()
is called. It moves the pointers in grid to
keep the player centered. The leading edge of grid is populated by map::load()
. If the submap has
been visited before, it’s loaded from MAPBUFFER. Otherwise a 2x2 chunk of submaps is generated based
on the corresponding overmap square type. An overmap encapsulates the large-scale structure of a map
(such as location and layout of cities, forests, rivers, roads, etc…). There are an arbitrary
number of overmaps. Additional overmaps are generated as the player enters new areas.
Q: What is the relation of NPCs/Monsters vs maps. How are they stored, where are they stored? Are they stored?
A: All npcs are now stored in the overmap. Active npcs only contain the currently active npcs. There is a difference between npc active npc coordinates, and overmap coordinates. So these will need to be changed when saving the npcs. Or else the npcs will be saved at the wrong location. And yes they are stored.