Commit graph

15 commits

Author SHA1 Message Date
smthspec
24538f365f Stop box stacking (clear location on spawn + self-healing sweep); split despawn timers
Stacking root cause: boxes that persisted from sessions before the
non-persistency change load into the world AFTER MissionServer.OnInit, so the
one-shot init cleanup missed them; they were untracked and never despawned, and
new boxes spawned on top.

- RemoveUntrackedBoxesAt(pos): deletes YALootBoxes_Base near a point that are
  NOT in m_ActiveBoxes (skips live boxes via IsTrackedBox), so it is safe to
  call any time.
- SpawnOneAtRandomFreeLocation now clears its exact location first, guaranteeing
  one box per location and never stacking on a leftover.
- CleanupOrphanedBoxes now runs at startup AND at the start of every
  TickLifecycle (self-healing), so ghosts that stream in late are removed within
  one check interval. Radius tightened 5m -> 3m.

Despawn timers (per request): split into two main_config keys
- DespawnMinutes: locked/unopened box lifetime (per-type despawnMinutes still
  overrides when > 0; default per-type is now 0 = use global).
- OpenedDespawnMinutes: lifetime after a box is opened.
Replaces the single DefaultDespawnMinutes. Lootbox uses GetLockedLifetimeMinutes
/ GetOpenedLifetimeMinutes accordingly. README/configfiles.readme + _comment docs
updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 12:37:56 +03:00
smthspec
ff51bde976 Fix open action (register custom action), stop restart-stacking, numeric log level, config docs
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>
2026-06-20 11:31:20 +03:00
smthspec
c6f6cea9ad Fix invisible boxes: use real SeaChest model + cargo grid
The placeholder model path (dz\structures\wood\wooden_crate.p3d) does not exist,
so boxes spawned invisible with no selection geometry - hence not visible and no
action (nothing to look at/target). Server logic was fine (8 boxes, proximity
msgs fired). YALootBoxes_Base now uses the vanilla SeaChest model
(\DZ\gear\camping\sea_chest.p3d) plus a 10x10 Cargo grid so the crate renders,
is targetable, and can hold loot. Verified model + texture paths exist locally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 01:11:10 +03:00
smthspec
f490d45001 Fix manager: string has no HashCode(); key cooldown map by UID string
GetPlainId() returns a string and string has no HashCode() in Enforce. Key the
per-player proximity cooldown map by the UID string directly (map<string,float>)
instead of an int hash. Verified the rest of the mod's engine calls against
P:\scripts (CreateObject/GetPlayerList/CallLater/RandomIntInclusive/etc.).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 00:19:19 +03:00
smthspec
249dcc6134 Fix action constructor: real anim constant + drop nonexistent member
CMD_ACTIONFB_ONCE does not exist in DayZPlayerConstants (only CMD_ACTIONMOD_*).
Use CMD_ACTIONMOD_OPENITEM (the 'open item' channel anim). Also remove
m_ReloadFinishAnim, which is not a member of ActionBase/ActionContinuousBase.
Verified the whole action file's symbols against P:\scripts vanilla source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 00:15:30 +03:00
smthspec
f7df4555cc Fix bleeding fail-effect API call
AttemptAddBleedingSourceByMaxCount() does not exist. Use the real API:
AttemptAddBleedingSource(component) with a valid component bit pulled from
GetBleedingSourcesLocations() (set<int>), looped chosen.bleedSources times.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 00:04:47 +03:00
smthspec
0dffa77caf Fix continuous-action timing: move CreateActionComponent to a callback class
ActionContinuousBase has no CreateActionComponent() to override (it lives on
ActionContinuousBaseCB). Added YALB_OpenLootboxCB : ActionContinuousBaseCB
overriding CreateActionComponent (CAContinuousTime in seconds), and pointed the
action at it via m_CallbackClass. Resolves the World-module compile error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:49:49 +03:00
smthspec
d28cebd5d6 Restructure: self-starting bootstrap + auto-provision all config files
Structure / module placement:
- Add scripts/5_Mission/YALootBoxes_MissionServer.c: a modded MissionServer
  that self-starts the manager in OnInit(). No init.c edit required anymore.
- config.cpp: bind 5_Mission to missionScriptModule (4_World stays on
  worldScriptModule). Core logic correctly stays in 4_World; only the
  mission-lifecycle bootstrap lives in 5_Mission.

Config create/read/write:
- LoadAll now writes populated defaults for ALL four JSON files when missing
  (previously only main_config.json was generated; box_types/loot_lists/
  spawn_locations were left empty, so a fresh install spawned nothing).
- Add default-data factories (YALB_MkReq/MkFail/MkLoot/MkLoc/MkBoxType) and
  DefaultBoxTypes/DefaultLootLists/DefaultSpawnLocations builders mirroring
  configfiles.readme. The mod is now self-provisioning on first run.

Docs:
- Prefix.cpp: refreshed folder-layout summary; dropped stale init.c /
  simulationModule notes.
- Manager.c: bootstrap comment now points to the 5_Mission self-start.
- README.md: add Install & first-run section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:44:43 +03:00
smthspec
910f972d3a Fix World-module compile error: invalid GetDuration override
The script log showed the only remaining error after the module-binding fix:
ActionContinuousBase has no GetDuration(ActionData) to override. Continuous
action timing is set via a CAContinuousTime component (in seconds) inside
CreateActionComponent(). Replaced the GetDuration override accordingly;
falls back to 5s on the client where MainConfig is null (config is
server-only, server stays authoritative on channel completion).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:28:03 +03:00
smthspec
663db39ab6 Fix server compile failure: script module binding + LogLevel name clash
Root causes from the script log of a failed boot:
- config.cpp bound the 4_World scripts to BOTH gameScriptModule and
  worldScriptModule. Compiling 4_World code inside 3_Game made PlayerBase,
  Container_Base, ActionContinuousBase and ActionData unknown types, which
  cascaded to YALootBoxes_Base and aborted the Game module. Now bound to
  worldScriptModule only.
- Static YALB_ConfigLoader.LogLevel collided with a framework type named
  LogLevel (CommunityFramework/DabsFramework). Renamed to ActiveLogLevel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:23:15 +03:00
smthspec
4b59c8e34b Add tools/Collect-YALootBoxesLogs.ps1 log collector for debugging
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:07:57 +03:00
smthspec
f38ae14409 Make open-action work as a client mod (resolve flagged issue #9)
The box-type config lives in $profile and loads server-side only, so the
client-side ActionCondition could never resolve required items and the
"Open lootbox" prompt would never appear.

- ActionCondition: show the prompt whenever the box is locked and the player
  holds any item; drop the client-impossible key-item check.
- OnFinishProgressServer: enforce the specific key-item requirement
  authoritatively; wrong/empty item now messages "Requires: X" and bails
  without rolling. All config stays server-only and admin-editable in $profile.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:02:43 +03:00
smthspec
f64425a840 Phase 3: leveled logging + green cleanups
Logging:
- Replace EnableDebugLogging (bool) with DebugLogLevel (string) in
  YALB_MainConfig; default "INFO". Stored as a string for admin-friendliness,
  parsed once at load into YALB_ConfigLoader.LogLevel (int) for cheap compares.
- Add YALB_LogLevel enum NONE(0)<ERROR(1)<WARN(2)<INFO(3)<DEBUG(4)<VERBOSE(5),
  YALB_ParseLogLevel (case-insensitive, falls back to INFO), and leveled
  helpers Log_Error/Warn/Info/Debug/Verbose. ERROR also routes via ErrorEx().
- Reclassify every existing log call by content (missing critical config ->
  ERROR, recoverable -> WARN, milestones -> INFO, per-tick summary -> DEBUG,
  per-player/per-roll detail -> VERBOSE). Add a VERBOSE proximity-send log.
- Update main_config.json example and the default constructor to "INFO".
- Add README.md documenting levels, the config field, and the VERBOSE warning.

Green cleanups (from Phase 2):
- Remove dead OnActionInfoUpdate override (behaviour is inherited).
- Remove unused m_LocationInUse map (the live pool is m_FreeLocationNames).
- Null-guard player identity in the fail-effect log.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 21:57:31 +03:00
smthspec
a84b6b1a2b Phase 2: structural/completeness fixes (correctness pass)
- config.cpp: fix script/config binding. Crates now inherit a shared
  YALootBoxes_Base config class (name-matches the script class) instead of
  relying on the non-binding simulationModule line. Base class changed from
  non-existent ContainerObject to vanilla Container_Base.
- Lootbox.c: same base class change; replace never-called GetActions
  override with the engine-correct SetActions()/AddAction().
- ActionOpen.c: BROKEN_BONE now uses player.SetBrokenLegs(eBrokenLegs.
  BROKEN_LEGS) instead of bogus GetHealthDamageManager().SetFracture();
  DecreaseHealth health-type arg empty-string changed to "Health" (3 sites).
- Config.c: restructure loot lists from a string-keyed map to a flat array
  of YALB_LootList{type,entries} for reliable JSON deserialization;
  GetLootListForType updated to linear scan; position made a ref array;
  document failEffects.chance as a weight, not a probability.
- loot_lists.json (configfiles.readme): match new array schema.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 21:49:37 +03:00
smthspec
354dfe34d5 Phase 1: rename audit complete (LootboxSpawner -> YALootBoxes)
- Renamed code prefix LB_ -> YALB_ across all four script files
- Renamed source files LootboxSpawner_*.c -> YALootBoxes_*.c
- Deleted three empty 0-byte stub files (_BoxTypes/_LootLists/_SpawnLocations)
- Fixed folder case scripts/4_world -> scripts/4_World to match config.cpp
- Verified box_types.json className values match CfgVehicles class names

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 21:27:38 +03:00