Action (the real "no action" cause): - DayZ does not auto-discover custom actions; ActionConstructor holds a hardcoded list and AddAction() silently drops anything missing from it. Added a modded ActionConstructor that registers YALB_ActionOpenLootbox, so the open action finally attaches to the box. - Switched the action target condition CCTObject -> CCTCursor (the look-at pattern vanilla uses for world-object interactions). Restart stacking: - Spawn boxes with CreateObjectEx + ECE_NOPERSISTENCY_WORLD so they are never saved to the world DB and don't survive restarts. - Added CleanupOrphanedBoxes(): on init, scan each spawn location and delete any leftover YALootBoxes_Base before spawning (clears boxes persisted before this change). Logging: - DebugLogLevel changed from a string to a numeric field (0=off 1=ERROR 2=WARN 3=INFO 4=DEBUG 5=VERBOSE), clamped at load. Removed the string parser. NOTE: existing main_config.json has a string value and must be regenerated. Config docs: - Each generated JSON now includes a "_comment" array describing every field and its range (ignored by the loader). README + configfiles.readme updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
489 lines
No EOL
19 KiB
C
489 lines
No EOL
19 KiB
C
// ============================================================
|
|
// YALootBoxes_Config.c
|
|
// Typed data classes for all JSON files + load/save/defaults.
|
|
// Lives in: scripts/4_World/YALootBoxes_Config.c
|
|
// ============================================================
|
|
|
|
const string YALB_CONFIG_DIR = "$profile:YALootBoxes\\";
|
|
const string YALB_MAIN_CONFIG_FILE = YALB_CONFIG_DIR + "main_config.json";
|
|
const string YALB_BOX_TYPES_FILE = YALB_CONFIG_DIR + "box_types.json";
|
|
const string YALB_LOOT_LISTS_FILE = YALB_CONFIG_DIR + "loot_lists.json";
|
|
const string YALB_SPAWN_LOCATIONS_FILE = YALB_CONFIG_DIR + "spawn_locations.json";
|
|
|
|
// ------------------------------------------------------------
|
|
// MAIN CONFIG
|
|
// ------------------------------------------------------------
|
|
class YALB_MainConfig
|
|
{
|
|
ref array<string> _comment; // admin-facing field docs (ignored by logic)
|
|
int MaxActiveLootboxes;
|
|
int GlobalCheckIntervalSeconds;
|
|
int DefaultDespawnMinutes;
|
|
int OpenChannelDurationSeconds;
|
|
float ProximityMessageRangeMeters;
|
|
int DebugLogLevel; // numeric verbosity, see _comment / YALB_LogLevel
|
|
|
|
void YALB_MainConfig()
|
|
{
|
|
// Sane defaults if file is missing/corrupt
|
|
MaxActiveLootboxes = 30;
|
|
GlobalCheckIntervalSeconds = 60;
|
|
DefaultDespawnMinutes = 15;
|
|
OpenChannelDurationSeconds = 5;
|
|
ProximityMessageRangeMeters = 3.0;
|
|
DebugLogLevel = 3; // INFO
|
|
_comment = {
|
|
"MaxActiveLootboxes: max boxes alive at once (1-100; also capped by number of spawn_locations).",
|
|
"GlobalCheckIntervalSeconds: seconds between despawn/respawn checks (10-600).",
|
|
"DefaultDespawnMinutes: fallback box lifetime if a box type omits despawnMinutes (1-1440).",
|
|
"OpenChannelDurationSeconds: hold-to-open time in seconds (1-30).",
|
|
"ProximityMessageRangeMeters: range of the 'Requires: X' hint, in meters (1-20).",
|
|
"DebugLogLevel: 0=off, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG, 5=VERBOSE."
|
|
};
|
|
}
|
|
};
|
|
|
|
// ------------------------------------------------------------
|
|
// BOX TYPES
|
|
// ------------------------------------------------------------
|
|
class YALB_RequiredItem
|
|
{
|
|
string classname;
|
|
string displayName;
|
|
};
|
|
|
|
class YALB_FailEffect
|
|
{
|
|
string type; // EXPLOSIVE, HEALTH, BLEEDING, SICKNESS, BROKEN_BONE
|
|
float chance; // RELATIVE WEIGHT for the single weighted pick - NOT an
|
|
// independent probability. Exactly one effect is chosen
|
|
// per failure; an effect's odds = its chance / sum(chances).
|
|
float damage; // used by EXPLOSIVE / HEALTH
|
|
float radius; // used by EXPLOSIVE
|
|
int bleedSources; // used by BLEEDING
|
|
string agent; // used by SICKNESS
|
|
};
|
|
|
|
class YALB_BoxTypeDef
|
|
{
|
|
string className;
|
|
string type;
|
|
ref array<ref YALB_RequiredItem> requiredItems;
|
|
float openChance;
|
|
float itemDamageOnOpen;
|
|
int despawnMinutes;
|
|
ref array<ref YALB_FailEffect> failEffects;
|
|
|
|
void YALB_BoxTypeDef()
|
|
{
|
|
requiredItems = new array<ref YALB_RequiredItem>();
|
|
failEffects = new array<ref YALB_FailEffect>();
|
|
openChance = 0.5;
|
|
itemDamageOnOpen = 5.0;
|
|
despawnMinutes = 15;
|
|
}
|
|
|
|
// Builds the player-facing "requires: X, Y" string
|
|
string GetRequiredItemsDisplayString()
|
|
{
|
|
string result = "";
|
|
for (int i = 0; i < requiredItems.Count(); i++)
|
|
{
|
|
if (i > 0) result += ", ";
|
|
result += requiredItems[i].displayName;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool IsValidKeyItem(string itemClassName)
|
|
{
|
|
for (int i = 0; i < requiredItems.Count(); i++)
|
|
{
|
|
if (requiredItems[i].classname == itemClassName)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
class YALB_BoxTypesFile
|
|
{
|
|
ref array<string> _comment;
|
|
ref array<ref YALB_BoxTypeDef> BoxTypes;
|
|
|
|
void YALB_BoxTypesFile()
|
|
{
|
|
BoxTypes = new array<ref YALB_BoxTypeDef>();
|
|
_comment = {
|
|
"className: must match a CfgVehicles class in the mod's config.cpp.",
|
|
"type: id linking this box to a loot_lists entry and to spawn_locations.",
|
|
"requiredItems: holding ANY one of these enables the open action (classname=item, displayName=shown text).",
|
|
"openChance: success probability, 0.0-1.0.",
|
|
"itemDamageOnOpen: damage dealt to the used tool on success (health points, >=0).",
|
|
"despawnMinutes: box lifetime in minutes, locked or after opening (1-1440).",
|
|
"failEffects: on failure exactly ONE is picked, weighted by 'chance' (weights need not sum to 1).",
|
|
" type: EXPLOSIVE | HEALTH | BLEEDING | SICKNESS | BROKEN_BONE.",
|
|
" damage: HP (EXPLOSIVE/HEALTH). radius: meters (EXPLOSIVE). bleedSources: count (BLEEDING).",
|
|
" agent: Salmonella|Influenza|Cholera|Brain|Wound_Bacterial (SICKNESS)."
|
|
};
|
|
}
|
|
};
|
|
|
|
// ------------------------------------------------------------
|
|
// LOOT LISTS
|
|
// ------------------------------------------------------------
|
|
class YALB_LootEntry
|
|
{
|
|
string classname;
|
|
float chance;
|
|
int minCount;
|
|
int maxCount;
|
|
};
|
|
|
|
// One loot list per box "type". Stored as a flat array of {type, entries}
|
|
// objects rather than a map<string, array<...>> - DayZ's JsonFileLoader is
|
|
// unreliable at deserializing nested generic containers (a map whose values
|
|
// are themselves ref arrays), whereas an array of typed objects deserializes
|
|
// dependably. Lookup is a small linear scan (only a handful of types).
|
|
class YALB_LootList
|
|
{
|
|
string type;
|
|
ref array<ref YALB_LootEntry> entries;
|
|
|
|
void YALB_LootList()
|
|
{
|
|
entries = new array<ref YALB_LootEntry>();
|
|
}
|
|
};
|
|
|
|
class YALB_LootListsFile
|
|
{
|
|
ref array<string> _comment;
|
|
ref array<ref YALB_LootList> LootLists;
|
|
|
|
void YALB_LootListsFile()
|
|
{
|
|
LootLists = new array<ref YALB_LootList>();
|
|
_comment = {
|
|
"type: must match a box_types 'type'. entries[] are rolled INDEPENDENTLY when a box opens.",
|
|
"classname: item to spawn. chance: 0.0-1.0 independent probability.",
|
|
"minCount/maxCount: quantity range when an item is rolled (integers, >=1, max>=min)."
|
|
};
|
|
}
|
|
};
|
|
|
|
// ------------------------------------------------------------
|
|
// SPAWN LOCATIONS
|
|
// ------------------------------------------------------------
|
|
class YALB_SpawnLocationDef
|
|
{
|
|
string name;
|
|
ref array<float> position; // [x, y, z] - 'ref' so the array member is owned/allocated
|
|
string boxType;
|
|
|
|
vector GetPosition()
|
|
{
|
|
if (position && position.Count() == 3)
|
|
return Vector(position[0], position[1], position[2]);
|
|
return vector.Zero;
|
|
}
|
|
};
|
|
|
|
class YALB_SpawnLocationsFile
|
|
{
|
|
ref array<string> _comment;
|
|
ref array<ref YALB_SpawnLocationDef> SpawnLocations;
|
|
|
|
void YALB_SpawnLocationsFile()
|
|
{
|
|
SpawnLocations = new array<ref YALB_SpawnLocationDef>();
|
|
_comment = {
|
|
"name: unique label for this spot. boxType: must match a box_types 'type'.",
|
|
"position: [x, y, z] world coords. Only one box spawns per location at a time.",
|
|
"Add as many locations as you like; boxes are placed at a random free one each cycle."
|
|
};
|
|
}
|
|
};
|
|
|
|
// ------------------------------------------------------------
|
|
// DEFAULT-DATA FACTORIES
|
|
// Small constructors used to build the first-run default files so
|
|
// the mod is self-provisioning. These mirror configfiles.readme.
|
|
// ------------------------------------------------------------
|
|
YALB_RequiredItem YALB_MkReq(string cls, string disp)
|
|
{
|
|
YALB_RequiredItem r = new YALB_RequiredItem();
|
|
r.classname = cls; r.displayName = disp;
|
|
return r;
|
|
}
|
|
|
|
YALB_FailEffect YALB_MkFail(string type, float chance, float damage = 0.0, float radius = 0.0, int bleed = 0, string agent = "")
|
|
{
|
|
YALB_FailEffect e = new YALB_FailEffect();
|
|
e.type = type; e.chance = chance; e.damage = damage; e.radius = radius;
|
|
e.bleedSources = bleed; e.agent = agent;
|
|
return e;
|
|
}
|
|
|
|
YALB_LootEntry YALB_MkLoot(string cls, float chance, int mn, int mx)
|
|
{
|
|
YALB_LootEntry l = new YALB_LootEntry();
|
|
l.classname = cls; l.chance = chance; l.minCount = mn; l.maxCount = mx;
|
|
return l;
|
|
}
|
|
|
|
YALB_SpawnLocationDef YALB_MkLoc(string name, float x, float y, float z, string boxType)
|
|
{
|
|
YALB_SpawnLocationDef d = new YALB_SpawnLocationDef();
|
|
d.name = name; d.boxType = boxType;
|
|
d.position = new array<float>();
|
|
d.position.Insert(x); d.position.Insert(y); d.position.Insert(z);
|
|
return d;
|
|
}
|
|
|
|
YALB_BoxTypeDef YALB_MkBoxType(string className, string type, float openChance, float itemDmg, int despawn)
|
|
{
|
|
YALB_BoxTypeDef b = new YALB_BoxTypeDef(); // requiredItems/failEffects arrays alloc'd in ctor
|
|
b.className = className; b.type = type;
|
|
b.openChance = openChance; b.itemDamageOnOpen = itemDmg; b.despawnMinutes = despawn;
|
|
return b;
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// LOADER / SAVER
|
|
// ------------------------------------------------------------
|
|
class YALB_ConfigLoader
|
|
{
|
|
static ref YALB_MainConfig MainConfig;
|
|
static ref YALB_BoxTypesFile BoxTypes;
|
|
static ref YALB_LootListsFile LootLists;
|
|
static ref YALB_SpawnLocationsFile SpawnLocations;
|
|
|
|
// Parsed-once numeric mirror of MainConfig.DebugLogLevel (see YALB_LogLevel).
|
|
// Defaults to INFO so logging behaves sanely before LoadAll() runs.
|
|
// NB: named ActiveLogLevel, not LogLevel - a loaded framework
|
|
// (CommunityFramework/DabsFramework) already defines a type 'LogLevel'.
|
|
static int ActiveLogLevel = YALB_LogLevel.INFO;
|
|
|
|
static void EnsureDirectoryExists()
|
|
{
|
|
if (!FileExist(YALB_CONFIG_DIR))
|
|
{
|
|
MakeDirectory(YALB_CONFIG_DIR);
|
|
}
|
|
}
|
|
|
|
// Loads each config file, writing a populated default if it is missing,
|
|
// so a fresh install is fully self-provisioning (boxes spawn on first run).
|
|
static void LoadAll()
|
|
{
|
|
EnsureDirectoryExists();
|
|
|
|
// --- main config (load, or save defaults) ---
|
|
MainConfig = new YALB_MainConfig();
|
|
bool createdMain = !FileExist(YALB_MAIN_CONFIG_FILE);
|
|
if (createdMain)
|
|
JsonFileLoader<YALB_MainConfig>.JsonSaveFile(YALB_MAIN_CONFIG_FILE, MainConfig);
|
|
else
|
|
JsonFileLoader<YALB_MainConfig>.JsonLoadFile(YALB_MAIN_CONFIG_FILE, MainConfig);
|
|
|
|
// Apply the configured level NOW (clamped to a valid range) so every
|
|
// log below honours it.
|
|
ActiveLogLevel = MainConfig.DebugLogLevel;
|
|
if (ActiveLogLevel < YALB_LogLevel.NONE) ActiveLogLevel = YALB_LogLevel.NONE;
|
|
if (ActiveLogLevel > YALB_LogLevel.VERBOSE) ActiveLogLevel = YALB_LogLevel.VERBOSE;
|
|
if (createdMain) Log_Info("main_config.json not found - created with defaults.");
|
|
|
|
// --- box types ---
|
|
if (FileExist(YALB_BOX_TYPES_FILE))
|
|
{
|
|
BoxTypes = new YALB_BoxTypesFile();
|
|
JsonFileLoader<YALB_BoxTypesFile>.JsonLoadFile(YALB_BOX_TYPES_FILE, BoxTypes);
|
|
}
|
|
else
|
|
{
|
|
BoxTypes = DefaultBoxTypes();
|
|
JsonFileLoader<YALB_BoxTypesFile>.JsonSaveFile(YALB_BOX_TYPES_FILE, BoxTypes);
|
|
Log_Info("box_types.json not found - created with defaults.");
|
|
}
|
|
|
|
// --- loot lists ---
|
|
if (FileExist(YALB_LOOT_LISTS_FILE))
|
|
{
|
|
LootLists = new YALB_LootListsFile();
|
|
JsonFileLoader<YALB_LootListsFile>.JsonLoadFile(YALB_LOOT_LISTS_FILE, LootLists);
|
|
}
|
|
else
|
|
{
|
|
LootLists = DefaultLootLists();
|
|
JsonFileLoader<YALB_LootListsFile>.JsonSaveFile(YALB_LOOT_LISTS_FILE, LootLists);
|
|
Log_Info("loot_lists.json not found - created with defaults.");
|
|
}
|
|
|
|
// --- spawn locations ---
|
|
if (FileExist(YALB_SPAWN_LOCATIONS_FILE))
|
|
{
|
|
SpawnLocations = new YALB_SpawnLocationsFile();
|
|
JsonFileLoader<YALB_SpawnLocationsFile>.JsonLoadFile(YALB_SPAWN_LOCATIONS_FILE, SpawnLocations);
|
|
}
|
|
else
|
|
{
|
|
SpawnLocations = DefaultSpawnLocations();
|
|
JsonFileLoader<YALB_SpawnLocationsFile>.JsonSaveFile(YALB_SPAWN_LOCATIONS_FILE, SpawnLocations);
|
|
Log_Info("spawn_locations.json not found - created with defaults.");
|
|
}
|
|
|
|
Log_Info(string.Format("Config loaded: %1 box types, %2 spawn locations, %3 loot lists. Log level = %4.",
|
|
BoxTypes.BoxTypes.Count(), SpawnLocations.SpawnLocations.Count(), LootLists.LootLists.Count(), MainConfig.DebugLogLevel));
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// First-run default builders (mirror configfiles.readme)
|
|
// ------------------------------------------------------------
|
|
static YALB_BoxTypesFile DefaultBoxTypes()
|
|
{
|
|
YALB_BoxTypesFile f = new YALB_BoxTypesFile();
|
|
|
|
YALB_BoxTypeDef mil = YALB_MkBoxType("YALootBoxes_Crate_Military", "military", 0.65, 8.0, 15);
|
|
mil.requiredItems.Insert(YALB_MkReq("BoltCutters", "Bolt Cutters"));
|
|
mil.requiredItems.Insert(YALB_MkReq("Crowbar", "Crowbar"));
|
|
mil.failEffects.Insert(YALB_MkFail("EXPLOSIVE", 0.15, 45.0, 2.5));
|
|
mil.failEffects.Insert(YALB_MkFail("HEALTH", 0.25, 15.0));
|
|
mil.failEffects.Insert(YALB_MkFail("BLEEDING", 0.30, 0.0, 0.0, 2));
|
|
mil.failEffects.Insert(YALB_MkFail("SICKNESS", 0.15, 0.0, 0.0, 0, "Salmonella"));
|
|
mil.failEffects.Insert(YALB_MkFail("BROKEN_BONE", 0.15));
|
|
f.BoxTypes.Insert(mil);
|
|
|
|
YALB_BoxTypeDef med = YALB_MkBoxType("YALootBoxes_Crate_Medical", "medical", 0.80, 4.0, 15);
|
|
med.requiredItems.Insert(YALB_MkReq("Hacksaw", "Hacksaw"));
|
|
med.failEffects.Insert(YALB_MkFail("SICKNESS", 0.50, 0.0, 0.0, 0, "Influenza"));
|
|
med.failEffects.Insert(YALB_MkFail("HEALTH", 0.30, 8.0));
|
|
med.failEffects.Insert(YALB_MkFail("BLEEDING", 0.20, 0.0, 0.0, 1));
|
|
f.BoxTypes.Insert(med);
|
|
|
|
YALB_BoxTypeDef ind = YALB_MkBoxType("YALootBoxes_Crate_Industrial", "industrial", 0.50, 12.0, 20);
|
|
ind.requiredItems.Insert(YALB_MkReq("Crowbar", "Crowbar"));
|
|
ind.requiredItems.Insert(YALB_MkReq("WeldingMask", "Angle Grinder"));
|
|
ind.failEffects.Insert(YALB_MkFail("EXPLOSIVE", 0.20, 60.0, 3.0));
|
|
ind.failEffects.Insert(YALB_MkFail("BROKEN_BONE", 0.25));
|
|
ind.failEffects.Insert(YALB_MkFail("BLEEDING", 0.30, 0.0, 0.0, 2));
|
|
ind.failEffects.Insert(YALB_MkFail("HEALTH", 0.25, 20.0));
|
|
f.BoxTypes.Insert(ind);
|
|
|
|
return f;
|
|
}
|
|
|
|
static YALB_LootListsFile DefaultLootLists()
|
|
{
|
|
YALB_LootListsFile f = new YALB_LootListsFile();
|
|
|
|
YALB_LootList mil = new YALB_LootList(); mil.type = "military";
|
|
mil.entries.Insert(YALB_MkLoot("AKM", 0.10, 1, 1));
|
|
mil.entries.Insert(YALB_MkLoot("Mag_AKM_30Rnd", 0.40, 1, 3));
|
|
mil.entries.Insert(YALB_MkLoot("PlateCarrierVest", 0.20, 1, 1));
|
|
mil.entries.Insert(YALB_MkLoot("TacticalHelmet", 0.15, 1, 1));
|
|
mil.entries.Insert(YALB_MkLoot("Ammo_762x39", 0.50, 1, 2));
|
|
f.LootLists.Insert(mil);
|
|
|
|
YALB_LootList med = new YALB_LootList(); med.type = "medical";
|
|
med.entries.Insert(YALB_MkLoot("Morphine", 0.30, 1, 1));
|
|
med.entries.Insert(YALB_MkLoot("SalineBagIV", 0.25, 1, 2));
|
|
med.entries.Insert(YALB_MkLoot("VitaminBottle", 0.50, 1, 3));
|
|
med.entries.Insert(YALB_MkLoot("Bandage", 0.60, 2, 5));
|
|
med.entries.Insert(YALB_MkLoot("TetracyclineAntibiotics", 0.20, 1, 2));
|
|
f.LootLists.Insert(med);
|
|
|
|
YALB_LootList ind = new YALB_LootList(); ind.type = "industrial";
|
|
ind.entries.Insert(YALB_MkLoot("WeldingMask", 0.15, 1, 1));
|
|
ind.entries.Insert(YALB_MkLoot("Battery_Car", 0.30, 1, 1));
|
|
ind.entries.Insert(YALB_MkLoot("SparkPlug", 0.40, 1, 2));
|
|
ind.entries.Insert(YALB_MkLoot("MetalPipe", 0.50, 1, 4));
|
|
ind.entries.Insert(YALB_MkLoot("DuctTape", 0.45, 1, 2));
|
|
f.LootLists.Insert(ind);
|
|
|
|
return f;
|
|
}
|
|
|
|
static YALB_SpawnLocationsFile DefaultSpawnLocations()
|
|
{
|
|
YALB_SpawnLocationsFile f = new YALB_SpawnLocationsFile();
|
|
f.SpawnLocations.Insert(YALB_MkLoc("NWAF_Hangar1", 4985.3, 320.5, 2456.8, "military"));
|
|
f.SpawnLocations.Insert(YALB_MkLoc("NWAF_Hangar2", 5102.7, 318.9, 2401.2, "military"));
|
|
f.SpawnLocations.Insert(YALB_MkLoc("Tisy_Bunker_A", 1606.4, 280.1, 14383.9, "military"));
|
|
f.SpawnLocations.Insert(YALB_MkLoc("Berezino_Hospital", 7245.1, 12.4, 13889.6, "medical"));
|
|
f.SpawnLocations.Insert(YALB_MkLoc("Zelenogorsk_Clinic",2543.9, 8.2, 5234.7, "medical"));
|
|
f.SpawnLocations.Insert(YALB_MkLoc("Tractor_Plant_1", 9821.2, 145.6, 8421.3, "industrial"));
|
|
f.SpawnLocations.Insert(YALB_MkLoc("Tractor_Plant_2", 9890.5, 142.1, 8390.7, "industrial"));
|
|
return f;
|
|
}
|
|
|
|
static YALB_BoxTypeDef GetBoxTypeByClassName(string className)
|
|
{
|
|
if (!BoxTypes) return null;
|
|
foreach (YALB_BoxTypeDef def : BoxTypes.BoxTypes)
|
|
{
|
|
if (def.className == className)
|
|
return def;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
static YALB_BoxTypeDef GetBoxTypeByType(string type)
|
|
{
|
|
if (!BoxTypes) return null;
|
|
foreach (YALB_BoxTypeDef def : BoxTypes.BoxTypes)
|
|
{
|
|
if (def.type == type)
|
|
return def;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
static array<ref YALB_LootEntry> GetLootListForType(string type)
|
|
{
|
|
if (!LootLists) return null;
|
|
foreach (YALB_LootList list : LootLists.LootLists)
|
|
{
|
|
if (list.type == type)
|
|
return list.entries;
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
|
|
// ------------------------------------------------------------
|
|
// LOGGING SYSTEM
|
|
// ------------------------------------------------------------
|
|
// Ordered severity. A message at level X is emitted only when the
|
|
// configured level >= X. NONE silences everything.
|
|
enum YALB_LogLevel
|
|
{
|
|
NONE = 0,
|
|
ERROR = 1,
|
|
WARN = 2,
|
|
INFO = 3,
|
|
DEBUG = 4,
|
|
VERBOSE = 5
|
|
};
|
|
|
|
// Shared gate + format for the non-error levels.
|
|
void YALB_Emit(int level, string tag, string msg)
|
|
{
|
|
if (YALB_ConfigLoader.ActiveLogLevel < level)
|
|
return;
|
|
Print("[YALootBoxes][" + tag + "] " + msg);
|
|
}
|
|
|
|
// ERROR is routed through ErrorEx() so it stands out in the .RPT, in
|
|
// addition to honouring the level gate. (ErrorEx is standard DayZ API.)
|
|
void Log_Error(string msg)
|
|
{
|
|
if (YALB_ConfigLoader.ActiveLogLevel < YALB_LogLevel.ERROR)
|
|
return;
|
|
ErrorEx("[YALootBoxes][ERROR] " + msg);
|
|
}
|
|
|
|
void Log_Warn(string msg) { YALB_Emit(YALB_LogLevel.WARN, "WARN", msg); }
|
|
void Log_Info(string msg) { YALB_Emit(YALB_LogLevel.INFO, "INFO", msg); }
|
|
void Log_Debug(string msg) { YALB_Emit(YALB_LogLevel.DEBUG, "DEBUG", msg); }
|
|
void Log_Verbose(string msg) { YALB_Emit(YALB_LogLevel.VERBOSE, "VERBOSE", msg); } |