Documentation - NUCLEAR-BOMB/dig-or-die-mods GitHub Wiki

Unofficial Dig Or Die API documentation

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.

CItemCell

Init

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).

CBulletDesc

Constructor

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 Sprites 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.

m_isPhysical

Not used anywhere in the game, possible scrapped prototype.

SWorldDll

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

DllGetSaveOffset

[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))

ResetDll

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.

CInventory

AddToInventory

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))).

InventorySorting

private int InventorySorting(CStack a, CStack b);

Returns (int)(a.m_item.m_id - b.m_item.m_id).

GBullets

CBulletDesc texture information

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)

SNetworkCommands

ProcessCommand

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

CUnit

GetRand

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.

Push

public virtual void Push(Vector2 force);

Pushes unit with force.

  • If this is CUnitBird applies half (0.5) of the force.
  • If this is CUnitBoss applies one tenth (0.1) of the force.
  • If this is CUnitWall applies half (0.5) of the force.

Note

These conditions can be applied simultaneously.

Update

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.

CUnit.CDesc

Fields

  • 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.

SLoc

The class specialized for text handling for the entire game.

GetText

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.

LoadLanguage

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.

SLoc.CSentence

Class that stores text ID and it's template (or static text).

Constructors

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.

GetText

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 {).

SScreenHudChat

OnInit

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.

CItem_MachineAutoBuilder

GetRecipes

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.

SDataLua

GetDescList

public static List<T> GetDescList<T>(string id);

Returns a list of preinitialized descriptors with Lua variable name id.

GetDesc

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

ClearAllDescs

private void ClearAllDescs();

Iterates over this.m_descMainTypes and dynamically creates generic SDataLua.CDesc_ListOf1Type<> and calls static method .Clear().

RegisterDesc

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).

GetLuaPath

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

IsUserTable

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).

OnInit

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 of CDesc can be used in Lua scripts).
    • If .BaseType is CDesc, add it to this.m_descMainTypes list.
  • 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 of int2 vector with x and y arguments.
    • Create (SDataLua.LuaCreate(string className)). Create new instance of type with name className using parameterless constructor.
    • Clone (SDataLua.LuaClone(CDesc prototype)). Clones descriptor using MemberwiseClone().
    • Debug (SDataLua.LuaDebug(object prototype)). Prints object and it's type (or - if prototype is null).

Execution stage:

  • Adds two module paths:
    1. Path to game's Mods folder that is located under DigOrDie_Data/StreamingAssets/Mods/{modName}/.
    2. Path to user's Mods folder that is located under Documents/Dig Or Die/<steam id>/Mods/{modName}/.
  • Calls module with name main.
    • Note that if main.lua exists in both places, the first one executes, and the second one is ignore.
  • Invokes string paramsDefault = Clone(params).
  • Overwrites two module paths:
    1. Path to game's Params folder that is located under DigOrDie_Data/StreamingAssets/Params/{modName}/.
    2. Path to user's Params folder that is located under Documents/Dig Or Die/<steam id>/Params/{modName}/.
  • 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 satisfies SDataLua.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 into SOutgame.ModesList dictionary with mod's name as a key.
  • Calls SDataLua.WriteDefaultParamsValues method for every mod name.
  • Sets mode to Solo (SOutgame.SetModeIFN("Solo")).

SDataLua.CDesc_ListOf1Type

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.

Add

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.

Clear

public static void Clear();

Clears CDesc_ListOf1Type<T>.m_list and sets CDesc_ListOf1Type<T>.m_idNumMax to 0.

SMisc

GetRandomCorrected

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).

GetIterators

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

CUnitMonster

UpdateTarget

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).

CLifeConditions

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.

CheckConditionsForPlant

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:

  1. The cell above is passable (IsPassable()).
  2. The cell altitude (j) is between m_altMin and m_altMax (inclusive).
  3. The blue component of the light (m_light.b) in the cell above is between m_lightMin and m_lightMax (inclusive).
  4. The water/lava in cell above is between m_waterAboveMin and m_waterAboveMax (inclusive).
  5. The water/lava in cell is between m_waterInMineralMin and m_waterInMineralMax (inclusive).
  6. 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))

  1. The plant cell is empty or contain the same type of plant.
  2. The mineral cell altitude (j) is between m_altMin and m_altMax (inclusive).
  3. The blue component of light (m_light.b) in plant cell is between m_lightMin and m_lightMax (inclusive).
  4. The water/lava in plant cell is between m_waterAboveMin and m_waterAboveMax (inclusive).
  5. If checkLava is true, then plant cell must contain lava if m_isFireProof is true, otherwise, it must not.
  6. The water/lava in mineral cell is between m_waterInMineralMin and m_waterInMineralMax (inclusive).
  7. If mineral cell has grass, then m_grass must be true, else m_nograss must be true.
  8. The mineral cell is not burning (CCell.Flag_IsBurning).

CSurface

Class for storing sprites (UnityEngine.Sprite) for rendering cells tiles.

Constructor

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).

SpTop

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)

InitSprites

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.

SUnits

OnUpdateSimu

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
  • Boss management:

    • Ensures at least 1 living boss per type exists in world/kill records
    • Kills duplicates furthest from home zone
    • Respawns bosses (CUnitBoss) after m_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)
  • Cleanup:

    • Removes null unit references and units with invalid id (whenm_unitsById returns null).
    • Sends updated unit position to the network
⚠️ **GitHub.com Fallback** ⚠️