Documentation - NUCLEAR-BOMB/dig-or-die-mods GitHub Wiki
This documentation consists of a descriptions of the game's internal logic. If you don't want to waste your time looking at decompiled code and thinking about it for hours, you are welcome.
It is, however, way be used as a more detailed wiki than the standard game's one.
Important
The documentation is incomplete and I don't think it will ever be.
The classes listed here are NOT only contains specified methods.
For more information, look at the game's decompiled code, don't only rely on the description provided here, it is incomplete and may skip aspects that are important to you.
- Unofficial Dig Or Die API documentation
When this.m_anchor == CItemCell.Anchor.Everywhere_Small
,
a sprite for the case when the object is not attached to anything, is created with this.m_tile.m_tileIndex.x + 1
(other arguments are passed unchanged).
The constructor accepts spriteTextureName
and spriteName
, and then creates sprite.
This internally uses the UnityEngine.Resources.LoadAll
to load all sprites from $Textures/{spriteTextureName}
.
Each loaded sprite has it's name, which must match with the spriteName
.
So, you need to patch the UnityEngine.Resources.LoadAll
(with parameters of types string
and Type
)
and return the array of Sprite
s if path
is equals to $Textures/{spriteTextureName}
with each name equal to their spriteName
.
Note
You can use Sprite.Create
to create new sprite with your custom texture.
The provided sprite's rect
is starts from the left bottom of the provided texture.
Also, the pivot
is scaled by rect
's width
and height
correspondingly, so if you have absolute pivot
you need to divide it by rect
's width
and height
to get relative.
The pixelsPerUnit
and extrude
are equal to their default values: 100f
and 0
.
The game uses the SpriteMeshType.FullRect
in meshType
, so you might choose to the standard option.
Other parameters should be defaulted.
Not used anywhere in the game, possible scrapped prototype.
The liquid physics, force processing, electricity processing and lighting processing are happening inside DigOrDie.dll
.
This file is located in <Dig or Die root>\DigOrDie_Data\Plugins\DigOrDie.dll
and compiled and linked with Microsoft Visual C/C++ (2017, v15.9) (Information is obtained with Detect It Easy
).
If you want to change the behavior related to the things listed above, you're out of luck.
Or you need to modify DigOrDie.dll
(which is directly the x86 machine code), or patch the wrappers around the DigOrDie.dll
functions.
The DigOrDie.dll
exports the following functions:
-
DllSetCallbacks
(accepts a callback for displaying debug information and a callback for calculating electricity production for specific cell) DllInit
DllResetSimu
DllClose
DllGetSaveOffset
GetBestSpawnPoint
DllProcessElectricity
DllProcessForces
DllProcessLightingSquare
DllProcessWaterMT
[DllImport("DigOrDie")]
private static extern int DllGetSaveOffset(int build, int x);
Computes a pseudo-random value between [0, 10] based on the x
argument (when build >= 198
).
Note that the result 10
is only appears once for all x
values at x = -1859131240
.
Reverse engineered C code:
uint32_t DllGetSaveOffset(int32_t build, int32_t x) {
if (build < 198) return 0;
uint32_t hash = x * 0x9e3779b1U; // Golden Ratio's fractional part
hash = ((hash >> 15) ^ hash) * 0x85ebca77U; // Some prime number
hash = ((hash >> 13) ^ hash) * 0xc2b2ae3dU; // Some prime number too
hash = (hash >> 16) ^ hash;
// ensures that return value is between [0, 10]
uint64_t product = (uint64_t)hash * 10ULL;
return (uint32_t)(product / 0xFFFFFFFFULL);
}
The function is used in world data serialization/deserialization to create an offsets between cells that are in the same Y coordinate. I don't fully understand the reason for this function to exists, perhaps obfuscate the data layout and complicate the reverse engineering process?
Proof that the returned values are between [0, 10] using Z3 solver (and that 10
appears only once):
import z3
x = z3.BitVec("x", 32)
hashV = x * 0x9e3779b1
hashV = (z3.LShR(hashV, 15) ^ hashV) * 0x85ebca77
hashV = (z3.LShR(hashV, 13) ^ hashV) * 0xc2b2ae3d
hashV = z3.LShR(hashV, 16) ^ hashV
product = z3.ZeroExt(32, hashV) * 10
res = z3.Extract(31, 0, product / 0xFFFFFFFF)
z3.solve(z3.Not(
z3.And(
z3.UGE(res, 0), # res >= 0
z3.ULE(res, 10) # res <= 10
)))
# z3.solve(z3.And(res == 10, x != 2435836056))
internal void ResetDll(int2 gs);
Creates an array of int2
with size (SWorld.Gs.x - 8) * (SWorld.Gs.y - 8)
and assigns it to m_gridOrder
.
Populates the m_gridOrder
with coordinates offsetted by 4 for each world's ends (e.g. for 1024x1024 world starts at (4,4)
and ends at (1020,1020)
).
Shuffles the m_gridOrder
using Fisher–Yates shuffle algorithm.
public CStack AddToInventory(CItem item, int nb = 1, bool selectIt = false, bool addItToBarIFN = true);
If the player already has this item, adds to the number of this current item.
Otherwise, creates a new stack of items (CStack
), append it to the list of the inventory items (m_items.Add
), sort the list of the inventory items by item's id (m_items.Sort(new Comparison<CStack>(this.InventorySorting))
).
private int InventorySorting(CStack a, CStack b);
Returns (int)(a.m_item.m_id - b.m_item.m_id)
.
Identical fields/properties.
pixelsPerUnit | texture | associatedAlphaSplitTexture | textureRectOffset | packed | border | hideFlags |
---|---|---|---|---|---|---|
100 | particles | null | (0.0, 0.0) | false | (0.0, 0.0, 0.0, 0.0) | None |
Name | textureRect | pivot | name | texture | bounds |
---|---|---|---|---|---|
plasma | (x:119.00, y:386.00, width:137.00, height:80.00) | (89.5, 41.6) | plasmaBig | particles | Center: (-0.2, 0.0, 0.0), Extents: (0.7, 0.4, 0.1) |
shotgun | (x:119.00, y:386.00, width:137.00, height:80.00) | (89.5, 41.6) | plasmaBig | particles | Center: (-0.2, 0.0, 0.0), Extents: (0.7, 0.4, 0.1) |
snipe | (x:119.00, y:386.00, width:137.00, height:80.00) | (89.5, 41.6) | plasmaBig | particles | Center: (-0.2, 0.0, 0.0), Extents: (0.7, 0.4, 0.1) |
laser | (x:61.00, y:115.00, width:111.00, height:19.00) | (55.5, 9.5) | laser | particles | Center: (0.0, 0.0, 0.0), Extents: (0.6, 0.1, 0.1) |
laserDrone | (x:61.00, y:115.00, width:111.00, height:19.00) | (55.5, 9.5) | laser | particles | Center: (0.0, 0.0, 0.0), Extents: (0.6, 0.1, 0.1) |
rocket | (x:55.00, y:88.00, width:83.00, height:21.00) | (61.4, 10.0) | rocket | particles | Center: (-0.2, 0.0, 0.0), Extents: (0.4, 0.1, 0.1) |
megasnipe | (x:0.00, y:258.00, width:255.00, height:119.00) | (178.6, 59.4) | plasmaHuge | particles | Center: (-0.5, 0.0, 0.0), Extents: (1.3, 0.6, 0.1) |
zf0bullet | (x:140.00, y:92.00, width:41.00, height:15.00) | (29.4, 8.0) | bullet | particles | Center: (-0.1, 0.0, 0.0), Extents: (0.2, 0.1, 0.1) |
laserGatling | (x:61.00, y:115.00, width:111.00, height:19.00) | (55.5, 9.5) | laser | particles | Center: (0.0, 0.0, 0.0), Extents: (0.6, 0.1, 0.1) |
grenade | (x:184.00, y:68.00, width:40.00, height:20.00) | (20.0, 10.0) | grenade | particles | Center: (0.0, 0.0, 0.0), Extents: (0.2, 0.1, 0.1) |
grenadeUltimate | (x:184.00, y:68.00, width:40.00, height:20.00) | (20.0, 10.0) | grenade | particles | Center: (0.0, 0.0, 0.0), Extents: (0.2, 0.1, 0.1) |
particlesShotgun | (x:265.00, y:98.00, width:163.00, height:82.00) | (114.3, 39.4) | particle_medium | particles | Center: (-0.3, 0.0, 0.0), Extents: (0.8, 0.4, 0.1) |
particlesSnipTurret | (x:239.00, y:0.00, width:209.00, height:98.00) | (143.5, 48.5) | particle_big | particles | Center: (-0.4, 0.0, 0.0), Extents: (1.0, 0.5, 0.1) |
particlesSnip | (x:239.00, y:0.00, width:209.00, height:98.00) | (143.5, 48.5) | particle_big | particles | Center: (-0.4, 0.0, 0.0), Extents: (1.0, 0.5, 0.1) |
flamethrower | (x:0.00, y:0.00, width:256.00, height:256.00) | (128.0, 128.0) | ParticleFirecloud | ParticleFirecloud | Center: (0.0, 0.0, 0.0), Extents: (1.3, 1.3, 0.1) |
defenses | (x:0.00, y:461.00, width:65.00, height:38.00) | (40.3, 19.0) | plasma | particles | Center: (-0.1, 0.0, 0.0), Extents: (0.3, 0.2, 0.1) |
firefly | (x:4.00, y:80.00, width:47.00, height:45.00) | (23.5, 22.5) | firefly | particles | Center: (0.0, 0.0, 0.0), Extents: (0.2, 0.2, 0.1) |
dweller | (x:108.00, y:3.00, width:51.00, height:35.00) | (25.5, 17.5) | mole | particles | Center: (0.0, 0.0, 0.0), Extents: (0.3, 0.2, 0.1) |
dwellerBig | (x:9.00, y:1.00, width:90.00, height:75.00) | (45.0, 37.5) | mole_big | particles | Center: (0.0, 0.0, 0.0), Extents: (0.5, 0.4, 0.1) |
particleSmall | (x:188.00, y:100.00, width:73.00, height:31.00) | (54.8, 16.0) | particle_small | particles | Center: (-0.2, 0.0, 0.0), Extents: (0.4, 0.2, 0.1) |
particleMedium | (x:265.00, y:98.00, width:163.00, height:82.00) | (114.3, 39.4) | particle_medium | particles | Center: (-0.3, 0.0, 0.0), Extents: (0.8, 0.4, 0.1) |
fireballSmall | (x:164.00, y:5.00, width:69.00, height:61.00) | (34.5, 30.5) | fireball_big | particles | Center: (0.0, 0.0, 0.0), Extents: (0.3, 0.3, 0.1) |
fireballBig | (x:164.00, y:5.00, width:69.00, height:61.00) | (34.5, 30.5) | fireball_big | particles | Center: (0.0, 0.0, 0.0), Extents: (0.3, 0.3, 0.1) |
grenadeLava | (x:391.00, y:275.00, width:99.00, height:95.00) | (49.5, 47.5) | fireball_huge | particles | Center: (0.0, 0.0, 0.0), Extents: (0.5, 0.5, 0.1) |
meteor | (x:391.00, y:275.00, width:99.00, height:95.00) | (49.5, 47.5) | fireball_huge | particles | Center: (0.0, 0.0, 0.0), Extents: (0.5, 0.5, 0.1) |
internal void ProcessCommand(string input, CPlayer playerSender = null);
Parses input
string and executes it as a command.
This function is executes on every client in the server with the same playerSender
.
If the command needs to be executed on only one client, it will be handled and filtered inside the function.
The chat history is also handled inside this function.
List of commands:
Command | Description | In-game help string |
---|---|---|
/allquitlobby |
Only works in multiplayer. Immediately closes lobby and exits to the main menu. Will not be stored in the command history buffer |
|
/system |
If the argument is in form CHAT_PICKED|<ITEM_ID>|<COUNT> it will display a message like Picked up: <ITEM_NAME> (<COUNT>) . If the argument is in form CHAT_DEATH_KILLED|<PLAYER_NAME>|<UNIT_ID> it will display a message like <PLAYER_NAME> was killed be a <UNIT_NAME> . Will not be stored in the command history buffer. |
|
/ban |
Host-only. Adds a player from the argument to ban list and creates a pop-up screen for the banned player in which, after they answers it, they will be kicked | <color='#afe8f5'>/ban player-name</color>: Ban a player (reset at game restart). Host only. Loop through names with (shift+) Tab key. |
/cleardaycounter |
Resets the number of survived nights to 0. (GVars.m_nbNightsSurvived = 0 ) |
<color='#afe8f5'>/cleardaycounter</color>: Reset the day counter to 1. |
/clearminimap |
Resets minimap to this undiscovered state. (SWorld.Grid[i, j].SetFlag(CCell.Flag_IsMapped, false) and SSingleton<SMinimap>.Inst.ReloadMinimapWorld() ) |
<color='#afe8f5'>/clearminimap</color>: Reset the minimap, everything go back to black (useful for map creation). |
/clearminimapfog |
Discover the entire world map. (SWorld.Grid[i, j].SetFlag(CCell.Flag_IsMapped, false) and SSingleton<SMinimap>.Inst.ReloadMinimapWorld() ) |
<color='#afe8f5'>/clearminimapfog</color>: Remove all the fog from the minimap (useful for map creation). |
/clearbosses |
Removes bosses respawn area and kills them | <color='#afe8f5'>/clearbosses</color>: Kill all bosses, and delete their lair/respawn area (use the Monster Gun in Dev Mode to recreate them). |
/clearkills |
Deletes all info about every killed specie except for Firefly (GUnits.firefly ) and Hound (GUnits.hound ). |
<color='#afe8f5'>/clearkills</color>: Clear the kill monster list, to reset the monsters spawned at night (keep only hounds and fireflies). |
/event |
Overrides current event by the provided one. Locks achievements in the current save. |
<color='#afe8f5'>/event event-name</color>: Activate a specfic event in 30s, even if the Hazardous Environment option is disabled. |
/find |
Searches the world from (13, 13) (inclusive) to (SWorld.Gs.x - 13 , SWorld.Gs.y - 13 ) (exclusive) and then pickups for cells/items containing provided code name in the argument. Only displays first 11 found cells/items. Note that it firstly searches for world's cells and then world's pickups. |
<color='#afe8f5'>/find item-name</color>: Find the positions of an item in the world. Item name is a part of the item code name (try 'autobuilder') |
/help |
Prints all commands and their usage. | <color='#afe8f5'>/help</color>: Display the list of chat commands. |
/kick |
Host-only. Creates a pop-up screen for the banned player in which, after they answers it, they will be kicked | <color='#afe8f5'>/kick player-name</color>: Kick a player. Host only. Loop through names with (shift+) Tab key. |
/killme |
Damages current player by G.m_player.GetHpMax() + 1000
|
<color='#afe8f5'>/killme</color>: Kill yourself. Could be useful if you manage to get stuck in multiplayer. |
/music |
Prints current playing music (or its absence if nothing is playing) | <color='#afe8f5'>/music</color>: Write the name of the currently played music. |
/param |
Host-only for modifications. Displays/assigns game's parameters (SOutgame.Params ) |
<color='#afe8f5'>/param param-name</color>: Draw a param value. Loop through params with (shift+) Tab key. <color='#afe8f5'>/param param-name = new-value</color>: Change a param value. Host only. Use with extreme caution, please read https://digordie.gamepedia.com/Custom_Params
|
public float GetRand();
Returns m_rand
. This value is always the same for each unit.
It is created for randomizing unit behavior and their animations for creating their uniqueness.
public virtual void Push(Vector2 force);
Pushes unit with force
.
- If
this is CUnitBird
applies half (0.5
) of theforce
. - If
this is CUnitBoss
applies one tenth (0.1
) of theforce
. - If
this is CUnitWall
applies half (0.5
) of theforce
.
Note
These conditions can be applied simultaneously.
internal virtual bool Update();
For every unit in the game the speed is clamped between -30
and 30
for X and Y axis.
The position is clamped between 0
and SWorld.GridRectM2.size.x
for X and 0
and SWorld.GridRectM2.size.y
for Y.
-
public string m_codeName
. -
public byte m_id
. -
public int m_tier
. Affects dropped blood tier, game tensions (SAudio.GetGameTension
) and displays screen message for hitting>1
tier monster. -
public string m_locTextId
. -
public float m_speedMax
. -
public float m_hpMax
. -
public int m_armor
. -
public Vector2 m_size
. -
public CTilesList m_anims
. -
public Color24 m_emitLight = default(Color24)
. Light that unit will emit. Default is none. -
public float m_canDive
. -
public bool m_immuneToFire
. -
public bool m_skipColsOnPlatforms
. -
public bool m_isSpawnPriority
.
The class specialized for text handling for the entire game.
public static string GetText(string id, bool forceRegenDynamic = false, string arg1 = null, string arg2 = null, string arg3 = null, string arg4 = null);
public static string GetText(string id, bool forceRegenDynamic, float arg1, float arg2 = -3.4028235E+38f, float arg3 = -3.4028235E+38f, float arg4 = -3.4028235E+38f);
Tries to retrieve text from the ID-text pair dictionary (SSingleton<SLoc>.Inst.m_dico
).
If it is failed to find one, logs warning and returns "-"
string.
Also caches any new combinations of text that is using arg1
, arg2
, arg3
and arg4
in the SSingleton<SResources>.Inst.m_dicoCachedTexts
.
private void LoadLanguage(string language, bool isDefault);
Reads localization strings and populates them into internal dictionary.
Checks if there is localization file (path Application.streamingAssetsPath + "/localization/" + language + ".txt"
); if not, logs error and returns.
Parses entire localization file to the internal dictionary to store it's data.
Caches any dynamically generated strings in SResources.GetCachedTextLoc
in the template form.
Class that stores text ID and it's template (or static text).
public CSentence(string id, string text);
Initializes class with id
and text
.
Replaces any \\n
with \n
.
If text
contains character {
it is considered dynamically generated, and it is depending on passed parameters.
Caches template text
string if it is generated.
public string GetText(bool forceRegenDynamic, string arg1 = null, string arg2 = null, string arg3 = null, string arg4 = null);
public string GetText(bool forceRegenDynamic, float arg1, float arg2 = 0f, float arg3 = 0f, float arg4 = 0f);
Retrieves localization string from cached dictionary, which depends on arg1
, arg2
, arg3
and arg4
.
If the text is not generated (m_textGenerated == null
) simply returns m_textStatic
.
Otherwise, uses SResources.GetCachedTextLoc
to try getting cached text string depending on arg1
, arg2
, arg3
and arg4
.
If forceRegenDynamic
is true, will forcibly regenerate cached string (if it is cached) and ignore incomplete string generation (has leftover {
).
protected override void OnInit();
Initializes m_txtChatLines
with 15 CGuiText
to display chat messages in the game.
Sets m_isRichText
to true
for each CGuiText
.
Also initializes m_txtChatLinesTime
with 15 float
with the value float.MinValue
.
Thus, in the game, can only be displayed maximum 15 lines of text in chat.
public List<CRecipe> GetRecipes();
Returns recipes that can be crafted using current autobuilder. This also initializes private field List<CRecipe> recipes
.
Reads a list of CRecipesGroup
from Lua variable with name list_recipesgroups
.
public static List<T> GetDescList<T>(string id);
Returns a list of preinitialized descriptors with Lua variable name id
.
public static T GetDesc<T>(string id) where T : CDesc;
Searches the current mode and its parent hierarchy for a descriptor of type T
with the specified id
and a matching mod name from the preinitialized list.
Returns the descriptor if found; otherwise, returns null
.
List of all available descriptors and their types that are defined in Lua scripts.
Name | Type |
---|---|
list_backgrounds |
CDescList (CBackground ) |
list_environments |
CDescList (CEnvironment ) |
mod |
CMode |
params |
CParams |
paramsDefault |
CParams |
aiMessagesSkipped |
CDescList (string ) |
list_musics |
CDescList (CMusic ) |
list_recipesgroups |
CDescList (CRecipesGroup ) |
jump |
CSound |
fall |
CSound |
fall_water |
CSound |
hurt |
CSound |
outOfAmmo |
CSound |
plasma |
CSound |
shotgun |
CSound |
plasmaSnipe |
CSound |
laser |
CSound |
particle |
CSound |
particleShotgun |
CSound |
storm |
CSound |
stormLight |
CSound |
rocketFire |
CSound |
rocketHit |
CSound |
defensePlasma |
CSound |
particleTurret |
CSound |
mine |
CSound |
ceilingTurret |
CSound |
firefly |
CSound |
hound |
CSound |
dweller |
CSound |
dwellerBoss |
CSound |
fish |
CSound |
birdBomb |
CSound |
monsterBat |
CSound |
ant |
CSound |
bossCrab |
CSound |
bossCrabScream |
CSound |
bossBird |
CSound |
miniBalrog |
CSound |
spiders |
CSound |
balrog |
CSound |
monsterParticleGround |
CSound |
monsterParticle |
CSound |
miniaturizor |
CSound |
rain |
CSound |
rocketCinematic |
CSound |
rocketExplosion |
CSound |
jetpack |
CSound |
waterfall |
CSound |
lava |
CSound |
fireForest |
CSound |
doorOpen |
CSound |
doorClose |
CSound |
teleport |
CSound |
potions |
CSound |
fireImpact |
CSound |
lavaEruption |
CSound |
alarm |
CSound |
private void ClearAllDescs();
Iterates over this.m_descMainTypes
and dynamically creates generic SDataLua.CDesc_ListOf1Type<>
and calls static method .Clear()
.
private void RegisterDesc(CDesc desc);
Traverses the inheritance chain of the given type upward, dynamically creating generic SDataLua.CDesc_ListOf1Type<>
with that deduced type and calling static method .Add(CDesc)
.
private string GetLuaPath(SDataLua.PathRoot pathRoot, SDataLua.Subpath subpath, string modName, string file = "?");
Returns a path to the Lua scripts location.
The default argument string file = "?"
is used as Lua module resolution paths, so this placeholder will be used on require
invocation.
pathRoot |
subpath |
Path |
---|---|---|
MyDocs |
Mods |
C:/Users/<user>/Documents/Dig Or Die/<steam id>/Mods/{modName}/{file}.lua |
Streaming |
Mods |
<steam apps>/Dig Or Die/DigOrDie_Data/StreamingAssets/Mods/{modName}/{file}.lua |
MyDocs |
Params |
C:/Users/<user>/Documents/Dig Or Die/<steam id>/Params/{modName}/{file}.lua |
Streaming |
Params |
<steam apps>/Dig Or Die/DigOrDie_Data/StreamingAssets/Params/{modName}/{file}.lua |
private bool IsUserTable(DynValue value);
Checks if value
is a table where all values are strings (DataType.String
) or all are (DataType.UserData
, type that represents custom .NET object).
protected override void OnInit();
Loads Lua descriptors for every available mod.
Preparation stage:
- Gathers all type in the current calling assembly:
- If the type is a subclass of
CDesc
, register it in Lua (e.g. all subclasses ofCDesc
can be used in Lua scripts). - If
.BaseType
isCDesc
, add it tothis.m_descMainTypes
list.
- If the type is a subclass of
- Set up custom Lua converters for types:
-
int2
. Impl:new int2((int)((double)dynVal.Table[1]), (int)((double)dynVal.Table[2])))
. -
IList<float>
. Impl:dynVal.Table.Values.Convert(DataType.Table)
.
-
- Adds Lua functions:
-
int2
(SDataLua.LuaInt2(int x, int y)
). Creates new instance ofint2
vector withx
andy
arguments. -
Create
(SDataLua.LuaCreate(string className)
). Create new instance of type with nameclassName
using parameterless constructor. -
Clone
(SDataLua.LuaClone(CDesc prototype)
). Clones descriptor usingMemberwiseClone()
. -
Debug
(SDataLua.LuaDebug(object prototype)
). Prints object and it's type (or-
ifprototype
isnull
).
-
Execution stage:
- Adds two module paths:
- Path to game's Mods folder that is located under
DigOrDie_Data/StreamingAssets/Mods/{modName}/
. - Path to user's Mods folder that is located under
Documents/Dig Or Die/<steam id>/Mods/{modName}/
.
- Path to game's Mods folder that is located under
- Calls module with name
main
.- Note that if
main.lua
exists in both places, the first one executes, and the second one is ignore.
- Note that if
- Invokes string
paramsDefault = Clone(params)
. - Overwrites two module paths:
- Path to game's Params folder that is located under
DigOrDie_Data/StreamingAssets/Params/{modName}/
. - Path to user's Params folder that is located under
Documents/Dig Or Die/<steam id>/Params/{modName}/
.
- Path to game's Params folder that is located under
- Calls module with name
params
.- If that modules doesn't exists, does nothing.
- Note that if
params.lua
exists in both places, the first one executes, and the second one is ignore.
- Copies every global value that is either
DataType.UserData
or satisfiesSDataLua.IsUserTable
in a new table. - Cleans up (removes) every global value that appears in the new table.
- Assigns a new variable with the mod's name that has the value of the new table.
- Repeat for all available mod's (
SOutgame.m_modNames
, that contains a list{ "Solo", "Multi", "SkyWorld", "UnderTheSea", "Defense" }
).
Post execution stage:
- Calls method
SDataLua.ClearAllDescs
. - For every mod:
- Gets a table in the globals with mod's name.
- Iterates that table and initializes and registers (
SDataLua.RegisterDesc
) the descriptors (CDesc
).
- Gathers descriptors for Lua variable
mod
and places them intoSOutgame.ModesList
dictionary with mod's name as a key. - Calls
SDataLua.WriteDefaultParamsValues
method for every mod name. - Sets mode to
Solo
(SOutgame.SetModeIFN("Solo")
).
private static class CDesc_ListOf1Type<T> where T : CDesc;
Purpose of this class is to store every instance of descriptor with type T
gathered from executing every world's Lua config files.
See SDataLua.RegisterDesc
and SDataLua.ClearAllDescs
.
public static void Add(CDesc desc);
Adds desc as T
to CDesc_ListOf1Type<T>.m_list
, increments CDesc_ListOf1Type<T>.m_idNumMax
and sets desc.m_idNum
to new value of CDesc_ListOf1Type<T>.m_idNumMax
.
public static void Clear();
Clears CDesc_ListOf1Type<T>.m_list
and sets CDesc_ListOf1Type<T>.m_idNumMax
to 0.
public static bool GetRandomCorrected(float chance, short id, CUnit attacker);
Computes a pseudo-random distribution of action succeeds while reducing extreme streaks of success or failure.
Instead of using raw randomness, it adjusts probabilities dynamically based on previous outcomes, making rare events more consistent and frequent events less streaky.
Used in monster loot dropping (CUnitMonster.GetRandomCorrected
).
public static void GetIterators(int n, double t, double dt, float period, out int it0, out int itn);
Used to determine which and how much cells to process in the current simulation step, ensuring the game's grid is updated smoothly over time.
Another way to understand this function is that by iterating through the grid in smaller segments (defined by it0
for the starting point and itn
for the number of cells to process) it ensures that every cell in the world is processed exactly once every period
seconds.
Name | Description |
---|---|
n |
Total number of cells |
t |
Current simulation time (e.g. GVars.m_worldTimeD ) |
dt |
Time elapsed since last simulation step (e.g. SMain.WorldDeltaTimeD ) |
period |
Time to process all cells once |
out it0 |
Starting index for cell processing |
out itn |
Number of cells to process in this step |
protected virtual void UpdateTarget();
Targets player by factors like:
- Last time player made sound.
- Unit is locking at player's direction.
Other units in 4 cell radius around also targets player and this propagates further on other units and so on.
If there is an aggressive boss, units also starts to target player regardless of distance.
If the player is 18 cells away, the target is reset (if the unit is not night spawned).
Name | Min/Max altitude | Min/Max light | Min/Max water above | Min/Max water in mineral | Fire proof | Grows on minerals | Grow chance (no nearby plants) |
Max nearby plants |
---|---|---|---|---|---|---|---|---|
dirt (grass) | 280/1024 | 95/255 | 0/0.2 | 0.01/9 | false | 0.2% | ||
dirtRed (grass) | 280/1024 | 95/255 | 0/0.2 | 0.01/9 | false | 0.2% | ||
silt (grass) | 280/1024 | 64/255 | 0.1/9 | 0.01/9 | false | 0.2% | ||
tree | 280/1024 | 95/255 | 0/0.8 | 0.01/1 | false | dirt, dirtRed | 0.2% | 0 |
treePine | 280/1024 | 95/255 | 0/0.8 | 0.01/1 | false | dirt | 0.2% | 0 |
treeWater | 280/1024 | 64/255 | 1.1/90 | 0.01/1 | false | silt | 0.2% | 0 |
treeSky | 0/1024 | 95/255 | 0/0.8 | 0/1 | false | dirtSky | 0.2% | 2 |
treeGranit | 0/280 | 95/255 | 0/1 | 0/1 | false | dirt | 0.2% | 2 |
bush | 280/1024 | 95/255 | 0/0.2 | 0.01/9 | false | dirt, dirtRed | 0.2% | 1 |
flowerBlue | 280/1024 | 95/255 | 0/0.2 | 0.01/9 | false | dirt | 0.2% | 1 |
flowerWhite | 0/1024 | 95/255 | 0/0.2 | 0.01/9 | false | dirtBlack | 0.2% | 1 |
fernRed | 280/1024 | 95/255 | 0/1.4 | 0.01/9 | false | dirtRed | 0.2% | 1 |
waterBush | 280/1024 | 64/255 | 0.15/1.7 | 0.01/9 | false | dirt, silt, dirtRed | 0.2% | 1 |
waterLight | 280/1024 | 0/255 | 0.15/90 | 0.01/9 | false | dirt, silt, dirtRed | 0.2% | 0 |
waterCoral | 280/1024 | 64/255 | 1.7/90 | 0.01/9 | false | dirt, silt, dirtRed | 10.2% | 1 |
blackGrass | 0/1024 | 0/25 | 0/0.2 | 0/1 | false | dirtBlack | 0.2% | 1 |
blackMushroom | 0/1024 | 0/25 | 0/0.2 | 0/1 | false | dirtBlack | 0.2% | 1 |
skyBush | 0/1024 | 95/255 | 0/0.2 | 0/1 | false | dirtSky | 0.2% | 1 |
lavaFlower | 0/1024 | 0/255 | 1/15 | 0/1 | true | lavaOld | 0.2% | 1 |
lavaPlant | 0/1024 | 0/255 | 15/99 | 0/1 | true | lavaOld | 0.2% | 1 |
bushGranit | 0/280 | 95/255 | 0/1 | 0/1 | false | dirt | 0.2% | 1 |
organicHair | 0/1024 | 95/255 | 0/1 | 0/1 | false | organicRock | 0.2% | 12 |
Note
There is also okIfNoGrass
and okIfGrass
, but they are always true
for all plants.
public bool CheckConditionsForGrass(int i, int j);
Checks if the conditions are fulfilled for the grass to grow relative to the position of the mineral.
Grass can grow if the conditions below are all satisfied:
- The cell above is passable (
IsPassable()
). - The cell altitude (
j
) is betweenm_altMin
andm_altMax
(inclusive). - The blue component of the light (
m_light.b
) in the cell above is betweenm_lightMin
andm_lightMax
(inclusive). - The water/lava in cell above is between
m_waterAboveMin
andm_waterAboveMax
(inclusive). - The water/lava in cell is between
m_waterInMineralMin
andm_waterInMineralMax
(inclusive). - The cell is not burning (
CCell.Flag_IsBurning
).
public bool CheckConditionsForPlant(int i, int j, CItem_Plant plant, bool checkLava = false);
Checks if the conditions are fulfilled for the plant to grow relative to the position of the mineral.
Plant can grow if the condition below are all satisfied:
Note
"Plant cell" is the cell above (e.g. at coordinates (i,j+1)
)
"Mineral cell" is the current cell (e.g. at coordinates (i,j)
)
- The plant cell is empty or contain the same type of plant.
- The mineral cell altitude (
j
) is betweenm_altMin
andm_altMax
(inclusive). - The blue component of light (
m_light.b
) in plant cell is betweenm_lightMin
andm_lightMax
(inclusive). - The water/lava in plant cell is between
m_waterAboveMin
andm_waterAboveMax
(inclusive). - If
checkLava
istrue
, then plant cell must contain lava ifm_isFireProof
istrue
, otherwise, it must not. - The water/lava in mineral cell is between
m_waterInMineralMin
andm_waterInMineralMax
(inclusive). - If mineral cell has grass, then
m_grass
must betrue
, elsem_nograss
must betrue
. - The mineral cell is not burning (
CCell.Flag_IsBurning
).
Class for storing sprites (UnityEngine.Sprite
) for rendering cells tiles.
public CSurface(string surfaceTexture, int surfaceSortingOrder, int topTileI = -1, int topTileJ = -1, bool hasAltTop = false, CSurface surfaceGrass = null, CSurface surfaceGrassWet = null, bool isGrassWet = false);
Initializes a surface object with texture and rendering properties.
It loads materials for the main surface (material: Materials/SurfaceOpaque
, texture: Textures/surfaces/{surfaceTexture}
) and top borders (material: Materials/SurfaceBorders
, texture: Textures/surfaces/_surface_tops
),
sets the sorting order, and configures optional grass/wet grass variants.
When top tile coordinates are provided, it creates tile sprites for surface borders (main, left, right, and optional alternate top).
public Sprite SpTop{ get { ... } }
Lazily initialized property that provides the main top border sprite for the surface. If the sprite (m_spTop
) hasn't been created yet, it triggers InitSprites()
, which generates the sprite from a texture atlas using predefined coordinates and dimensions (96x64 pixels)
public void InitSprites();
Initializes the border sprites (m_spTop
, m_spTopAlt
, m_spTopL
, m_spTopR
) by slicing them from a shared texture atlas (Textures/surfaces/_surface_tops
).
It calculates their position based on m_topTileCoords
, but for wet grass variant (isGrassWet
) it grabs 512 pixels below.
The main top sprite (m_spTop
) uses a 96x64 region, while left/right borders (m_spTopL
, m_spTopR
) are 16x64.
If m_hasAltTop
is true, an alternate top sprite is also created that is 64 pixels below.
All sprites use a pivot at the bottom center (for proper alignment) and a fixed pixels-per-unit (100).
Note
The coordinates in Sprite.Create
starts at the bottom-left corner of the texture,
but the game subtracts Y position from texture.height
so it's actually starts at top-left origin,
and you need to specify topTileI
and topTileJ
in that format.
protected override void OnUpdateSimu();
Simulation update method handling unit management, monster spawning, boss logic, and defense systems.
-
Unit updates:
- Iterates through all units and updating them, if the update was unsuccessful (e.g. dead, decomposed) removes those units
- Counts alive monsters (
CUnitMonster
) - Detects active boss units (
CUnitBoss
) (aggressive/nearby states) - Removes player units (
CUnitPlayer
) if their associated network player left/disconnected
-
Monster spawning:
- Night/Rocket/Eclipse spawns: spawns monsters using formula:
Gm_nightSpawnFrequency[difficulty] * deltaTime * paramsMult * playerCountMult* environmentMult
(attempts up to 10 spawns per frame when accumulatedspawn) - Day spawns: maintains minimum monster count per player with cooldown
- Handles both normal and "creative spawn" monsters differently
- Night/Rocket/Eclipse spawns: spawns monsters using formula:
-
Boss management:
- Ensures at least 1 living boss per type exists in world/kill records
- Kills duplicates furthest from home zone
- Respawns bosses (
CUnitBoss
) afterm_bossRespawnDelay
seconds
-
Defense units:
- Removes defense units (
CUnitDefense
) when corresponding grid item on the same cellmissing (CItem_Defense
) - Removes defense units (
CUnitDefense
) when players is not around them (exceptm_neverUnspawn
defenses)
- Removes defense units (
-
Cleanup:
- Removes
null
unit references and units with invalid id (whenm_unitsById
returnsnull
). - Sends updated unit position to the network
- Removes