dayz-basebuilding
Skill20 starsChanged 42 days agoMITView on GitHub
Author, extend and debug DayZ buildable structures on BaseBuildingBase: fences, watchtowers, gates, walls, shelters, tents, flag poles and barbed wire. Covers kit recipe/deploy/hologram flow, Construction{} fields, BaseBuildingBase/Construction/ConstructionPart/ConstructionActionData, required/conflicted parts, build/dismantle/destroy actions, synced-bitmask persistence, damage-zone mapping and the Fence gate state machine. Use for "base won't save", parts reset/disappear after restart, construction part or action missing, CanBuild/CanBuildPart, RegisterPartForSync, blocked dismantle, missing collision or hologram placement. Always invoke before authoring/debugging a buildable structure or its persistence. Delegate geometry to dayz-model-pipeline, script APIs to enforce-script-reference, persistence audit to rigorous-data-audit and packaging to dayz-pbo-build. Also 1.30 Exp: ConstructionBase/Rebuilding, BuildPartServerEx, bricks/mortar, fence code lock. Not terrain holes: dayz-underground.
In this repository47 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- 3d-generation-harnessSkill
- ai-3d-to-dayzSkill
- ardy-motion-generationSkill
- blender-animationSkill
- blender-assemblySkill
- blender-visual-reviewSkill
- dayz-3d-viewerSkill
- dayz-ai-patternsSkill
- dayz-animation-pipelineSkill
- dayz-aviationSkill
- dayz-charactersSkill
- dayz-clothingSkill
- dayz-doorsSkill
- dayz-environment-hazardsSkill
- dayz-feature-specSkill
- dayz-mcp-verifySkill
- dayz-model-pipelineSkill
- dayz-mod-workflowSkill
- dayz-motorbikesSkill
- dayz-p3d-auditSkill
- dayz-p3d-inspectorSkill
- dayz-particlesSkill
- dayz-pbo-buildSkill
- dayz-pbo-reverse-engineeringSkill
- dayz-persistenceSkill
- dayz-physics-engineSkill
- dayz-preflightSkill
- dayz-proxy-alignSkill
- dayz-realistic-animation-directorSkill
- dayz-sound-systemSkill
- dayz-test-ingameSkill
- dayz-texture-pipelineSkill
- dayz-ui-developmentSkill
- dayz-undergroundSkill
- dayz-vehiclesSkill
- dayz-weaponsSkill
- enforce-script-referenceSkill
- mixamo-retargetSkill
- ovh-cloudSkill
- rigorous-data-auditSkill
- rip-vehicle-importSkill
- systematic-debuggingSkill
- task-observerSkill
- uv-clean-atlasSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 0 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 121
Every field's reader lives in construction.c — cited in references/config-contract.md.
- Very specific: line 253
Do NOT build new features on ActionPlugIntoFence — it is DEPRECATED (actionplugintofence.c:1).
- Very specific: line 308
ConstructionActionData.SetSlotId/GetSlotId: Not deleted. [Obsolete("1.30: Unsafe, overridden ActionData used in-system instead")] …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
DayZ Base Building
Buildable player structures in DayZ — fences, watchtowers, gates, shelters, flag poles — are built by
extending the vanilla BaseBuildingBase chain, not from EntityAI. Inheriting BaseBuildingBase
gives you the whole system for free: the per-part build/dismantle/destroy action set, the synced-bitmask
persistence, the hologram deploy flow, and the damage-driven part destruction. The only things you author
are a .p3d with the right selections + memory points and a config Construction{} block that declares
each buildable part.
This skill owns the base-building-specific layer. Generic geometry, config-script mechanics, packaging and data-critical audit are delegated to the skills in the table below.
The whole system is ~6 script files + 1 config block. All path:line citations here point at real vanilla
source under P:\scripts\ (= <dayz-projects>\scripts\) and
DZ\gear\camping\config.cpp. Verify against those before writing any class name or field.
(until 1.29: that ~6-file count). (since 1.30 Exp: ConstructionBasic in 3_Game, ConstructionBase /
Construction / Rebuilding in 4_World, plus ConstructionPartTypeData on EntityType. Full map in
references/dayz-1-30-construction-rebuilding.md.)
THE MODEL — kit → deploy → build → upgrade → dismantle
The four-class quartet and who owns what:
| Class | Role | Where |
BaseBuildingBase: ItemBase | the persisted world entity; owns one ref Construction, the sync ints, events, physics, area damage | basebuildingbase.c:2 |
Construction | per-instance controller; holds map<string, ref ConstructionPart> keyed by part config-class name; does ALL config lookups live | construction.c:11 |
ConstructionPart | runtime record of one part (name, m_Id bit index, built/base/gate flags, required parts) | constructionpart.c:1 |
ConstructionActionData | per-player scratch state on PlayerBase; caches which parts are buildable under the cursor, drives radial action variants | constructionactiondata.c:1 |
ConstructionBasic | (since 1.30 Exp:) 3_Game stub + EntityAI hooks CreateConstructionComponent() / GetConstructionBasic() | Construction_Basic.c:2; EntityAI.c:3441-3479 |
ConstructionBase : ConstructionBasic | (since 1.30 Exp:) shared 4_World controller; BuildPartServerEx / DismantlePartServerEx / IsCollidingEx | ConstructionBase.c:30,174,185,1471 |
Rebuilding : ConstructionBase | (since 1.30 Exp:) map-building restoration on BuildingBase; ten m_SyncParts* ints | Rebuilding.c:1; Building.c:23-26 |
ConstructionPartTypeData | (since 1.30 Exp:) type-level cached Construction{} fields; instance ConstructionPart holds mutable state | ConstructionPartTyped.c:2 |
Construction is NOT itself persisted — it is rebuilt from config on every load and its part states are
restored from the sync bitmask (see PERSISTENCE). End-to-end flow:
(until 1.29: BaseBuildingBase owned ref Construction m_Construction and ConstructionPart stored config
fields per instance). (since 1.30 Exp: the field is protected ref ConstructionBasic m_Construction
(basebuildingbase.c:15); CreateConstructionComponent() does new Construction(this) (:871-875);
GetConstruction() is Construction.Cast(m_Construction) (:883-886). Config is cached once per
EntityType in ConstructionPartTypeData and attached via SetPartTypeData (ConstructionPart.c:383-389;
ConstructionBase.UpdateConstructionParts :495-532).)
- Craft the kit. A
RecipeBase(craftfencekit.c:1) consumes materials → aKitBase: ItemBase(kitbase.c:1,IsBasebuildingKit()→true:5). - Deploy (hologram). Kit
SetActions()addsActionTogglePlaceObject+ActionDeployObject(kitbase.c:146-152);ActionDeployObject.ActionUsesHologram()→true(actiondeployobject.c:15). On finish the SERVER spawns the real entity —FenceKit.OnPlacementComplete(fencekit.c:19-34)CreateObjectEx("Fence", …)+HideAllSelections()— and the kit self-deletes onOnEndServer(actiondeployobject.c:230-234). - Base part. The spawned entity has NO parts built. Player attaches the base material then builds the
basepart (is_base=1). Building it setsHasBase()=true, spawns a construction kit back, and toggles the"Deployed"proxy/animation (OnPartBuiltServerbasebuildingbase.c:592-598;InitVisuals:770-784). - Build part.
ActionBuildPart(actionbuildpart.c:25) with a tool in hand →OnFinishProgressServer(:112-130) re-checks collision +CanBuildPart→construction.BuildPartServer(...)(construction.c:75-95): reset damage-zone health,TakeMaterialsServer, register the part in the sync bitmask, show physics+visual, regen navmesh. (until 1.29:BuildPartServer(player, part_name, action_id)). (since 1.30 Exp:ActionBuildPartcallsBuildPartServerEx(actionbuildpart.c:170); the old method is[Obsolete("call BuildPartServerEx instead")]and forwards (ConstructionBase.c:1688-1694). OverrideBuildPartServerEx, not the obsolete wrapper.) - Upgrade = building further parts whose
required_parts[]are satisfied (HasRequiredPartconstruction.c:412-435) and whoseconflicted_parts[]are not built (HasConflictPart:438-455). - Dismantle.
ActionDismantlePart(actiondismantlepart.c:26) →DismantlePartServer(:98-118) refunds materials. Blocked if the partHasDependentPart(construction.c:479-496). Dismantling the base part destroys the whole construction (basebuildingbase.c:653-657). (until 1.29:DismantlePartServer). (since 1.30 Exp:DismantlePartServerEx(ConstructionBase.c:185); obsolete wrapper:1696-1702.HasDependentPartnow lives onConstructionBase:758.) - Fold. With no base and no attachments (
CanFoldBaseBuildingObject:1067-1075),ActionFoldBaseBuildingObjectconverts back to a kit in hands (FoldBaseBuildingObject:1077-1083).
THE Construction{} CONFIG BLOCK (the single most-reused artifact)
Two-level nesting: Construction { class <main_part> { class <part> {...} } }. Annotated from the Fence
block (config.cpp:4527-4585). Full field-by-field in references/config-contract.md.
class Construction {
class wall { // main_part_name (m_MainPartName)
class base { // part_name — config class == m_PartName AND the p3d selection
name="$STR_..._Part_Base"; // localized display name
is_base=1; // foundation part; dismantling it destroys the whole entity
id=1; // UNIQUE sync/persistence bit index, 1..93 (see PERSISTENCE)
required_parts[]={}; // parts that must be built first
conflicted_parts[]={}; // parts that block this one if already built
collision_data[]={}; // {min_memorypoint, max_memorypoint} for the build collision box
build_action_type=4; // bitmask AND-matched against the tool's build_action_type
dismantle_action_type=4;
material_type=1; // ConstructionMaterialType — drives build/dismantle SFX
class Materials {
class Material1 {
type="WoodenLog"; // item classname (used when refunding piles)
slot_name="Material_WoodenLogs"; // attachment slot the material sits in
quantity=2; // consumed; -1 = delete whole object; 0 = ignore qty
lockable=1; // 1 = lock material in slot instead of consuming it
};
};
};
}
}Every field's reader lives in construction.c — cited in references/config-contract.md. The entity class
itself declares attachments[] (material/attachment slots), hybridAttachments[] (health mirrors a damage
zone), mountables[] (proxy-physics toggled, e.g. barbed wire), and a DamageSystem { class DamageZones }.
PREFLIGHT — the hard invariants
Gate real build work on /dayz-preflight (P:\ mounted, AddonBuilder, P:\Mods junction) per
_shared/dayz-conventions.md. Authoring config offline does not need it; packing does. Before declaring a
base-building entity done, verify ALL of these — each is a silent-corruption source:
idMUST be unique and in 1..93 across the wholeConstruction{}block. The id is a bit index into three 31-bit sync ints; a duplicate or out-of-range id collides in the bitmask and corrupts part state (RegisterPartForSyncbasebuildingbase.c:148-175). This caps a single entity at 93 distinct parts. (until 1.29: that 93-part cap was the only packing). (since 1.30 Exp: it still holds for everyBaseBuildingBase—RegisterPartForSyncis unchanged (basebuildingbase.c:137-164) andOnStoreSavestill writesm_SyncParts01/02/03thenm_HasBase(:420-430).RebuildingonBuildingBaseis a different stream: ten intsm_SyncParts1..10, 2 bits per part,REBUILDING_STORAGE_VERSION = 1(Rebuilding.c:3,7-16,502-515). Do not mix the two caps.)- Damage-zone name MUST equal the part name, lowercased.
EEHealthLevelChangedlowercases the zone and looks up the part by that name (basebuildingbase.c:507-517); a mismatch means damage never destroys the part. Fence.OpenFence()does not consult the combination lock.CanOpenFence()requiresHasHinges() && !IsOpened() && !IsLocked()(fence.c:427-434).IsLocked()is a closedCombinationLock(fence.c:115-124).OpenFence()skips that check, plays the gate animations and callsSetOpenedState(true)(fence.c:447-465). A script that callsOpenFence()directly opens a locked fence. Test!IsLocked()or callCanOpenFence()first.CanCloseFence()does not require the lock to be open (fence.c:437-444). Source-verified 2026-09-28 againstP:\scripts\4_world\entities\itembase\basebuildingbase\fence.c.OnStoreSave/OnStoreLoadorder is strict. Save writesm_SyncParts01,02,03, thenm_HasBase(basebuildingbase.c:420-430); load reads them in the same order (:432-464). A subclass writes/reads its extra fields AFTER callingsuper, in the exact same order both ways (Fence appends gate state after the three ints —fence.c:212-220/:222-255). Reordering silently corrupts every saved base.- Every
part_nameMUST be both an AnimationSource in config AND a selection in the.p3d. Show/hide isSetAnimationPhase(part_name, 0/1)(construction.c:578-588, phase 0 = visible); the base uses the"Deployed"proxy instead. A missing selection/memory point → the part builds but has no visual or no collision. - Action-type ints (
_constants.c:6-8):AT_BUILD_PART=193,AT_DISMANTLE_PART=195,AT_DESTROY_PART=209. Passed intoBuildPartServer/DismantlePartServer/DestroyPartServerand synced so clients play the right SFX. (since 1.30 Exp: pass them intoBuildPartServerEx/DismantlePartServerEx. Tool masks now includeEConstructionTools.TOOL_BRICKLAYING = 256(ConstructionConstants.c:25).) - How much of a material fits in one slot is decided by the SLOT's
stackMax, NOT by the item'svarQuantityMax. For a splitable item,GetTargetQuantityMaxasksInventorySlots.GetStackMaxForSlotIdfirst and only falls back tovarStackMax, then tovarQuantityMax(itembase.c:3473-3490). Vanilla declares the cap per slot inscripts\config.cpp:Material_WoodenPlanksandMaterial_MetalSheetsarestackMax=20(:2266-2281),Material_Nailsis99(:2260-2264). A NON-splitable item skips that branch entirely and lands onvarQuantityMax—MetalWiredeclares no quantity and neither of its slots declaresstackMax(:2290-2296,:2349-2355), so it is one wire per slot. Reading the item class instead overstates plank capacity 5× (100 vs 20) and makes any recipe above the slot cap silently unbuildable: the player fills the slot and never reaches the threshold, so the build action simply never appears. Derive slots per material asceil(default_qty / slot stackMax)and get that number fromCfgSlots, not from the item. Any design promising a uniform configurable range ("1..100 of each material") is broken before it is written. Origin: caught by an independent plan review after the item-class reading had already been written into a spec — the item's ceiling exists, it just is not the one that governs. - The same fallback sets a crop's harvest yield: raising its
varStackMaxchanges the vanilla yield (DayZ 1.30.164014 Exp) [EXACT][CLAIM-HARVEST-YIELD-STACKMAX-130]:PlantBase.Harvestcreates each crop pile withSetQuantity(GetQuantityMax())(4_World/Entities/GardenBase/PlantBase.c:575-576), and for a splitable itemGetQuantityMaxresolves tovarStackMaxwhen the slot declares no stack max (4_World/Entities/ItemBase.c:3436-3469).SetQuantityclamps to[min, max](4_World/Entities/ItemBase.c:3353), so a scripted yield above the stack size was silently clipped until the mod replaced the harvest quantity. - A green/red placement hologram needs TWO declarations, and neither is the one the name
suggests.
Hologram.RefreshVisualtints by callingSetObjectTexture/SetObjectMaterialon a hidden-selection index (hologram.c:1546-1565). That index comes fromGetHiddenSelection, which falls back to 0 when the name is absent (:1523-1531) — so a model with nohiddenSelections[]in config silently renders the ghost in its normal material, with no error anywhere. And the config entry alone is not enough: the model must expose that selection as retexturable viasections[]inmodel.cfg, or the swap has nothing to bind to. DeclarehiddenSelections[]+hiddenSelectionsTextures[]+hiddenSelectionsMaterials[]with the values the model already uses (so normal rendering is unchanged), and put the same selection insections[]. Note the hologram never looks the name up: it asks forplacing/inventory(:40-43,178-194) and lands on index 0 regardless, so the name only maps index 0 to a real section. Also declarehologramMaterial+hologramMaterialPath; the engine appends_deployable.rvmat/_undeployable.rvmat(:14-16). Cost of learning this the hard way: one in-game cycle, plus a review finding that was raised, retired as a likely false positive, and turned out to be true. itemBehaviourdoes NOT choose the in-hands carry pose. The int drives behaviour rules and the deploy command (itembase.c:65:0 = heavy, 1 = onehanded, 2 = twohanded), but the pose comes from class registration in the anim graph. Vanilla registers every heavy object explicitly — barrel atdayzplayercfgbase.c:817, wooden crate at:830— throughModItemRegisterCallbacks.RegisterHeavy(:305,:317) callingAddItemInHandsProfileIK(class, … player_main_heavy.asi, pBehavior, … .anm). With no registration the item falls back to theInventory_Baseone-handed default and is carried in one hand no matter whatitemBehavioursays. The.anmis an IK pose, not a class binding, so reusing a vanilla one for a different class is fine and needs no new animation. Pick the value from the object family you are imitating, not from a mod that ships a different shape: a cabinet is0like the barrel, not2like a small kit box.SetActionsaddsActionTogglePlaceObject+ActionPlaceObjectonly in the deployable subclass (container_base.c:32,48-54), which is whatBarrel_ColorBaseinherits from (barrel_colorbase.c:1). A storage entity extendingContainer_Basegets no placement at all, andIsDeployable()isfalseby default (itembase.c:4380-4383). Adding the two actions to the single class that needs them is cheaper than reparenting a shared base and cannot regress its siblings. The ghost material comes fromhologramMaterial+hologramMaterialPath(hologram.c:1554-1557) plus the suffixes_deployable.rvmat/_undeployable.rvmat(:14-16); declare both keys or the hologram renders untextured.- A custom wall-placement hologram (modded
Hologram.UpdateHologram) needs four things vanilla does not hand you. (1) The wall normal: neitherRaycastRVProxy.dirnorRaycastRV.contactDiris a face normal for object hits — both are the ray direction, so a yaw taken from them faces the camera and the ghost's box collides with the wall at any angle. Take it fromDayZPhysics.RayCastBulletonPhxInteractionLayers.BUILDINGand keep the fire-geometry ray for identity (enforce-script-referenceSP-LFS-2). (2) The ground: pick the nearest support at or BELOW the aimed point (Y ≤ aimY + 2 mm); a ray started 2 m above the point selects sills, ledges and the floor above. (3) The collision box: lift its bottom 5 cm likeIsCollidingBBox(hologram.c:547,556) or every building floor blocks placement, and trim the back so the support wall does not count. (4) One diagnostic line per cause bit (wall/ground/spacing/ player/water/box), emitted on change and rate-limited, each line under 255 chars, with the unlifted box queried only when logging — that is what turned "the hologram is grey" into a named cause in one cycle. Origin: LFSecure, 2026-09-09, three in-game cycles and two Codex rounds (LFSecure_dev/plans/2026-09-09-colocacion-fix-diag.md); (1) shipped but not yet exercised in-game.
PERSISTENCE — one synced bitmask is BOTH netsync AND save (data-critical)
Part-built state is NOT stored per part; it is packed into three 31-bit ints m_SyncParts01/02/03
(basebuildingbase.c:12-14), which serve as both the netsync representation and the persistence format.
Part id 1..31 → SyncParts01, 32..62 → SyncParts02, 63..93 → SyncParts03. On load,
SetPartsFromSyncData rebuilds each part's built flag from the bitmask and reconciles physics/visuals
(SetPartFromSyncData :276-315, which also failsafe-relocks attached materials against corrupted data).
R9 gate: any mod that adds parts, changes the bitmask packing or the id ranges, or touches
OnStoreSave/OnStoreLoad ordering is modifying player progression — a bug means lost bases after a
restart. Delegate to rigorous-data-audit (R9) BEFORE declaring release-safe. Full detail, the 93-part
cap, the version bumps (GetDamageSystemVersionChange()→111; Fence gate persistence bumped at v110) and
the hand-off checklist are in references/persistence-audit.md.
(since 1.30 Exp: BaseBuildingBase packing is unchanged. Rebuilding is a second, versioned stream on
map buildings — see references/persistence-audit.md §8 and references/dayz-1-30-construction-rebuilding.md.
CombinationLock on a Fence now also writes m_CombinationInside at vanilla stream v143
(CombinationLock.c:128-136,169-177) — a subclass OnStoreLoad that skips that branch desyncs the item.)
QUICK TRIAGE
| Symptom | Likely cause | Where |
| Base won't save / parts reset on server restart | OnStoreSave/OnStoreLoad order broke, or a subclass wrote fields before super / in a different order | PERSISTENCE; references/persistence-audit.md |
| A built part doesn't show (visual missing) | part_name is not an AnimationSource in config or not a selection in the .p3d | PREFLIGHT show/hide; dayz-animation-pipeline, dayz-model-pipeline |
| A built part has no collision | missing per-part proxy memory/selection, or (base) missing "Deployed" proxy | dayz-model-pipeline (+ dayz-p3d-audit) |
| Part state corrupts / two parts toggle together | duplicate or out-of-range id in Construction{} (bitmask collision) | PREFLIGHT id≤93; RegisterPartForSync basebuildingbase.c:148-175 |
| Damage never destroys a part | damage-zone name ≠ part name lowercased | PREFLIGHT zone==part; basebuildingbase.c:507-517 |
| The build action never appears | tool's build_action_type doesn't AND-match the part's, or CanBuildPart fails (missing/ruined material, required part, conflict) | construction.c:296-304, 959-1003 |
| Dismantle is blocked | the part HasDependentPart (something built depends on it) | construction.c:479-496 |
| "built but not shown until sync" in single-player | ConstructionPart.SetRequestBuiltState skips the local set in SP and waits for sync | constructionpart.c:56-63 |
| Placement / hologram won't confirm | height check or collision fails on the hologram | actiondeployobject.c:42-75; references/entity-lifecycle.md |
| Perf hitch when building | UpdatePhysics() is a "massive performance hit" per the code's own warning | basebuildingbase.c:838 — avoid frequent calls |
Override of BuildPartServer never runs (1.30) | vanilla actions now call BuildPartServerEx | actionbuildpart.c:170; ConstructionBase.c:1688-1694 |
Compile error on CreateCollisionTrigger (1.30) | methods still exist but are [Obsolete("no replacement")]; collision is IsCollidingEx(CollisionCheckData) | ConstructionBase.c:1471,1742-1787 |
| Rebuilt house / well part resets | mixed up BaseBuildingBase 3-int save with Rebuilding 10-int HandleStoreSave | Rebuilding.c:474-515; Building.c:23-45 |
| Fence code lock ignored | slot is Att_CodeLock; getter is Fence.GetCodeLock() | fence.c:20,26,161-165 |
| Powered opener opens a locked fence | caller used OpenFence() and skipped CanOpenFence() / IsLocked() | fence.c:115-124,427-465 |
Do NOT build new features on ActionPlugIntoFence — it is DEPRECATED (actionplugintofence.c:1).
DELEGATIONS
| Concern | Skill |
.p3d selections / memory points / the Deployed proxy / LODs / missing-collision or action-target bugs | dayz-model-pipeline (+ dayz-p3d-audit) |
config.cpp + Enforce script — RPC, sync vars, OnStoreSave/Load, modded class, side checks | enforce-script-reference |
| Persistence / bitmask packing / recovery paths (data-critical, id ranges, save ordering) | rigorous-data-audit (R9) |
Show/hide a part (SetAnimationPhase), gate open/close, AnimationSources | dayz-animation-pipeline |
| Build / deploy / launch to test; smoke it in-game | dayz-pbo-build + dayz-test-ingame (+ dayz-mcp-verify) |
Terrain holes, underground triggers, disallowedTypesInUnderground, bunkers under the terrain | dayz-underground |
CITE-THEN-VERIFY
Base-building class and field names are easy to half-remember. Before writing a class name, base, config
field or named selection, grep vanilla (P:\scripts\4_world\, DZ\gear\camping\config.cpp) or the cited
reference. The id/damage-zone/selection invariants above corrupt data silently when wrong — verify them
against the real .c and .p3d, never from memory.
REFERENCES
references/config-contract.md— theConstruction{}block,Materials,GUIInventoryAttachmentsProps,attachments[]/hybridAttachments[]/mountables[], toolbuild_action_type, DamageZones↔part mapping, every field with its readerpath:line.references/entity-lifecycle.md— the deploy→build→sync→persist→load call chain hop by hop withpath:line(hologram,OnPlacementComplete,OnPartBuiltServer,SetPartFromSyncData,AfterStoreLoad), plus the action set andAT_*ints.references/fence-gate-case.md— the Fence worked example: gate state machine, open/close animation, combolock, barbed-wire area damage, and the v110 gate-persistence version bump.references/persistence-audit.md— the three-int bitmask packing, the 93-part cap,OnStoreSave/Loadordering, the version bumps, and the R9 hand-off checklist.references/dayz-1-30-construction-rebuilding.md— 1.30 Exp hierarchy (ConstructionBasic/ConstructionBase/Rebuilding),ConstructionPartTypeData,*ServerEx/IsCollidingEx, obsolete collision-trigger wrappers, brick/mortar/trowel loop, FenceDigitalCodeLock.
Rules promoted from lessons learned corpus (added 2026-07-27)
Promoted from AI/20_Knowledge/lessons-learned.md so they trigger automatically rather
than depending on someone remembering to look them up. Each rule cites its originating LL-NNN;
the full entry (symptom, origin, evidence) lives there. Do not remove citation: the index
lessons-index.md detects promotion by searching for that reference inside the skills.
- LL-042 — Create an eponymous script class for each placeable config class and inherit from kit/static base providing
SetActions,IsDeployable, and the kit↔static link. Verify both halves before diagnosing hologram or textures.
DayZ 1.30 Exp (build 1.30.164014)
Digest J (work/out2/digest-J-construction-locks-bunker.md §§1,3–5). Every class/method below was re-opened under exp\scripts\scripts\. Digest line numbers were often wrong; citations here are from the files.
What changes
- Hierarchy.
EntityAI.CreateConstructionComponent()(EntityAI.c:3451) returns null by default.BaseBuildingBaseoverrides it tonew Construction(this)(basebuildingbase.c:871-875).BuildingBaseoverrides it tonew Rebuilding(this)(Building.c:23-26). Field type on both isprotected ref ConstructionBasic m_Construction. - Static vs instance.
ConstructionPartTypeDatacachesConstruction{}onEntityType(ConstructionPartTyped.c:2-67).ConstructionPartkeepsm_PartTypeData,m_LocalSyncBitMask,m_IsBuilt(ConstructionPart.c:9-12). The old multi-arg constructor is empty (:14-16); instances areToType().Spawn()thenSetPartTypeData(ConstructionBase.c:514-520). *ServerEx.BuildPartServer/DismantlePartServer/IsCollidingare[Obsolete]wrappers onConstructionBase(:1688-1740). Live path:BuildPartServerEx/DismantlePartServerEx/IsCollidingEx(CollisionCheckData)(:174,185,1471). Digest J'sIsCollidingEx(string, Object, bool, bool)signature is not in the file.- Collision triggers.
CreateCollisionTrigger/DestroyCollisionTrigger/IsTriggerCollidingare not deleted. They are[Obsolete("no replacement")](ConstructionBase.c:1742-1787). Calling them still compiles; do not build new code on them. ConstructionActionData.SetSlotId/GetSlotId. Not deleted.[Obsolete("1.30: Unsafe, overridden ActionData used in-system instead")](constructionactiondata.c:617-627).- Rebuilding (map buildings, not player fences).
BuildingBaseregistersm_Construction.m_SyncParts1..10(Building.c:29-45). Packing:BIT_INT_SIZE = 32(BitArray.c:4) × 10 ints /BITWISE_SYNCINFO_SIZE_BASE = 2(ConstructionPart.c:6) = 160 part ids. Persist viaHandleStoreSave→SerializeConstructionData(Rebuilding.c:474-515). Default build mask sets bit 0;ConstructionPartRebuildalso stores facing in bit 1 (:985-991). Digest J's 00/01/10 "ruined" table was not found in those methods. - Masonry loop.
PileOfBricks+ActionPickUpBricks.YIELD = 3(ActionPickUpBricks.c:16-18).MortarMixmixes at water/well (MortarMix.c:6-7) intoMortarMix_Opened.BrickTroweladdsActionBuildPart(BrickTrowel.c:1-7); build animCMD_ACTIONFB_BRICKTROWEL(actionbuildpart.c:260-262). Tool mask enumTOOL_BRICKLAYING = 256(ConstructionConstants.c:25).[UNVERIFIED]CfgVehicles BrickTrowel build_action_type— class not in extracted configs. - Fence locks.
FencehasATTACHMENT_CODE_LOCK = "Att_CodeLock"andGetCodeLock()(fence.c:20,26,161-165) beside the existing combination lock. Dialing a combo lock no longer unlocks it:ActionCombinationLockUnlock(CombinationLock.c:686). - Material enum moved.
ConstructionMaterialTypenow lives onConstructionBase.c:2-12and addsMATERIAL_BRICK = 6,MATERIAL_RUBBLE = 7. disableSimulation.[CHANGELOG]house entities may setdisableSimulationto skip ticking (changelog-1.30-exp-modding.md:13; nativeEntity.c:3-6). Not aBaseBuildingBasefield.- Activation. Any
CfgVehiclesclass with aConstructionsubclass gets the component at init (EntityAI.c:248-249). Rebuilding parts read new keys: per-part decay (can_part_decay,part_decay_threshold,part_decay_rate, globaldisableBaseDecay),StaticsSupportData,EffectsData,custom_part_type,skipOnRepair/skipOnDismantle. Table with readers:references/dayz-1-30-construction-rebuilding.md§9.2. - Rebuildable map buildings are scripts only in 1.30 Exp. The Nasdara houses and
Land_IrrigationTunnel_Entrance_01have script classes but no configs or models in the Exp install (§9.4). Terrain holes and underground areas:dayz-underground. - Rebuildable houses carry attachment slots on the building itself (DayZDiag 1.30.164200) [EXACT][CLAIM-BB-130-HOUSE-SLOTS]: in that build the configs are there (the line above describes 1.30.164014). A server-side scan of
CfgVehicles(classes thatIsKindOf "House",scope≥ 1, non-emptyattachments[]) found 32 classes: 22 houses fromLand_House_1M1toLand_House_3S2_Dam2, whose rebuild slots areRB_LvL<n>_{Log,Plank,Nail,MetalSheet,MetalWire}plusRB_LvL<n>_{Brick,MortarMix}on all butLand_House_1M1,Land_House_1M2andLand_House_1S1, with<n>up to 1 on the1*houses, 2 on the2*and 3 on the3*, and lock slotsAtt_CombinationLock<n>_{Wood,Metal}/Att_CodeLock<n>_{Wood,Metal}in a number that varies per house;Land_Bunker_Basement_*/Land_Bunker_Shelter_*withAtt_CodeLock,Land_WaterWell_Brick,Land_IrrigationTunnel_Entrance_01(RB_LvL1/2_{Rope,Stick}) andLand_Radio_PanelBig/Land_Radio_PanelPAS(LargeBattery).world_spawn(Land_House_1M1)on Chernarus answereddeclared_slotswith the nine level-1 slots, andinventory_attach(WoodenPlank, slot RB_LvL1_Plank)filled one. Moves into and out of those slots reachItemBase.EEItemLocationChangedwith the house as the hierarchy root (enforce-script-reference,references/dayz-1-30-enforce-script.md§3.2). Script class:Land_House_1M1 : BuildingSuper(4_World/Entities/Building/Rebuildable/House_1M1.c:1); slot rules inBuildingBase.CanReceiveAttachment/CanReleaseAttachment(4_World/Entities/Game/Super/Building.c:192,:267). Not measured: the Nasdara map itself, models and rebuild actions on these slots.
What breaks (1.29 mods)
- Override of
BuildPartServer/DismantlePartServeris skipped if vanilla calls*Ex. Migrate the override. - New code that called
CreateCollisionTriggerstill compiles but is obsolete with no replacement — useIsCollidingEx(CollisionCheckData)(ConstructionBase.c:1471,1896-1910). - Direct typed access to
m_ConstructionasConstructionfails: field isConstructionBasicandprotected. UseGetConstruction()orGetConstructionBasic(). - Instantiating
ConstructionPartwith the old constructor does not fill type data. Spawn +SetPartTypeData. - Fence combo-lock automation that assumed "last dial = unlocked" needs
ActionCombinationLockUnlock. - Custom
CombinationLock.OnStoreLoadmust readm_CombinationInsidewhenversion >= 143.
Migration checklist
- Replace overrides of
BuildPartServer/DismantlePartServer/IsCollidingwith*Ex. - Stop using construction-box triggers; build
CollisionCheckDataand callIsCollidingEx. - Access construction via
GetConstruction()/GetConstructionBasic(), never the raw field from outside. - Keep
BaseBuildingBaseidin 1..93 and theOnStoreSaveorder01,02,03,m_HasBase. - Do not write Rebuilding's 10-int stream into a
BaseBuildingBasesubclass. - If attaching a code lock to a Fence, use slot
Att_CodeLockandDigitalCodeLock. - If subclassing
CombinationLock, handle stream v143. - R9-audit any bitmask /
OnStoreSavechange (references/persistence-audit.md).
Detail
references/dayz-1-30-construction-rebuilding.md (EXACT blocks), references/persistence-audit.md §8, references/config-contract.md §8, references/entity-lifecycle.md §2/§4, references/fence-gate-case.md §6.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

