| Last updated | 16 hours ago |
| Total downloads | 8 |
| Total rating | 1 |
| Categories | Rundown Tools |
| Dependency string | cris-SupplyCrate-0.0.1 |
| Dependants | 0 other packages depend on this package |
README
SupplyCrate
Place crates anywhere in a level through a JSON config. A crate can either hand out resource packs (ammo / medi / tool / disinfection) or swap the player's gear (primary, special, melee or tool). Each crate has a limited number of uses, can switch between several presets ("profiles") at runtime, can be turned on and off with a custom warden event, and can fire warden events when it runs out.
- Live edit. Save the config while in a level and the crates are rebuilt immediately.
- Optional PartialData support. ID fields such as
MainLevelLayoutcan use PartialData GUID names.
Usage
{
"Prefab": "Assets/MyAssets/SupplyCrate.prefab",
"Levels": [
{
"MainLevelLayout": 100, // LevelLayoutDataBlock ID (or PartialData name)
"Crates": [
{
"WorldEventObjectFilter": "AmmoCrate_A", // unique name of this crate
"Category": "Resource",
"Position": { "x": 12.5, "y": 0.0, "z": -40.2 },
"Rotation": { "x": 0, "y": 90, "z": 0 },
"ProfileList": [
{ "Index": 0, "Type": "Ammo", "PackUses": 3, "Limit": 4 }
]
}
]
}
],
"LiveEdit": true,
"DebugLog": false
}
Config reference
Levels
| Field | Type | Description |
|---|---|---|
MainLevelLayout |
uint / PartialData name | The LevelLayoutDataBlock this entry applies to. |
Crates |
array | Crates spawned in this level. See Crate definition. |
Crate definition
| Field | Type | Default | Description |
|---|---|---|---|
WorldEventObjectFilter |
string | required | The crate's name. It must be unique within the level. Events use it to find the crate. |
Category |
Resource / Gear |
Resource |
Resource hands out resource packs. Gear swaps gear. (Weapon is accepted as an old name for Gear.) |
Enabled |
bool | true |
Whether the crate starts enabled. |
Position |
{x,y,z} |
0,0,0 |
World position. |
Rotation |
{x,y,z} |
0,0,0 |
Euler angles in degrees. |
InteractDuration |
float | 2.5 |
Seconds the player has to hold the interact key. A negative value keeps the prefab's value. |
ProfileList |
array | [] |
Presets. The first entry in the list is active when the level starts. See below. |
EventsOnUsed |
array of warden events | [] |
Executed every time the crate runs out of uses. See EventsOnUsed. |
TerminalItemKey |
string | "" |
Optional. If set, and the prefab has an LG_GenericTerminalItem, the crate is registered as a terminal item KEY_<serial> (for example SUPPLY_CRATE_123). Leave it empty to skip. |
DimensionIndex |
enum | Reality |
Only used for the terminal item: the zone it is listed under. |
Layer |
enum | MainLayer |
Same as above. |
LocalIndex |
enum | Zone_0 |
Same as above. |
AreaIndex |
int | 0 |
Same as above. This is the area within the zone. |
Profiles (common fields)
| Field | Type | Default | Description |
|---|---|---|---|
Index |
int | 0 |
The ID used by SetCrateStatus to switch to this profile. It does not need to match the profile's position in the list. |
Type |
string | required | For resource crates: Ammo, Medi, Tool or Disinfect. For gear crates: Uniform or Map. |
Limit |
int | -1 |
Number of uses, shared by the whole team. When the count reaches 0, the crate is depleted. -1 means unlimited. Switching to a profile resets the remaining uses to its Limit. |
A resource crate may only contain resource settings, and a gear crate may only contain gear settings. Any field that belongs to the other category is ignored, and a warning is written to the log.
Profiles: resource crates
{ "Index": 0, "Type": "Medi", "PackUses": 2, "Limit": 3 }
| Field | Type | Default | Description |
|---|---|---|---|
Type |
Ammo / Medi / Tool / Disinfect |
Which pack is given. It also selects the UI sprite and the interaction title. | |
PackUses |
int | 1 |
Number of uses in the pack the player receives. One use equals 20 ammo in the pack. |
ItemID |
uint | by type | Optional override of the ItemDataBlock. The defaults are Ammo 101, Medi 102, Tool 127 and Disinfect 132. |
The pack is spawned and picked up by the interacting player straight away.
Profiles: gear crates
All gear references (From, To) point to a PlayerOfflineGearDataBlock. You can write either:
- the persistentID, as a number (
300) or a numeric string ("300"), or - the block's
name, as a string ("Gear_Shelling_S49"). If several blocks share a name, the one that comes first in the DataBlock is used.
Blocks with internalEnabled: false can be used too. This lets you make weapons that cannot be picked in the lobby and can only be obtained from a crate.
Valid slots are Standard (primary), Special, Melee and Tool (Class means the same as Tool).
Uniform: everyone gets the same gear
{
"Index": 0,
"Type": "Uniform",
"Limit": 4,
"GearList": [
{ "Slot": "Standard", "To": 300 },
{ "Slot": "Special", "To": "Gear_Mastaba_R66" }
]
}
- If
GearListhas several entries, the slot that is swapped depends on what the player is holding. A player holding their primary gets theStandardentry, a player holding their special gets theSpecialentry, and so on. If the held slot is not in the list, nothing can be swapped. - If
GearListhas exactly one entry, that slot is swapped no matter what the player is holding.
Map: per-weapon replacement table
{
"Index": 1,
"Type": "Map",
"Limit": 3,
"GearMap": [
{ "From": 300, "To": 4700 },
{ "From": 4700, "To": "Gear_Bataldo_Custom_K330" }
]
}
- The plugin checks the gear the player is holding: primary, special, melee or tool.
- The held gear is looked up in
From. If it is found, it is replaced by the matchingTo. - Chains are allowed. A weapon obtained from the crate can be swapped again by another entry, for example A → B and then B → C.
Rules for both modes
- Same slot only.
FromandTo(Map), orSlotandTo(Uniform), must belong to the same inventory slot. The slot comes from the gear's base item. Entries that break this rule are skipped, and an error is logged that names the entry and both slots, for example:Crate 'GearCrate_1': Map profile 1 GearMap[0] skipped: From 'X' is GearStandard, To 'Y' is GearSpecial - Entries with a missing or unknown
From/Toare skipped and logged. - If the player already has the target gear, or nothing in the table matches, the crate cannot be used. The player can still aim at it, and the prompt shows "current weapon cannot be swapped". No use is consumed.
Warden event: SetCrateStatus (Type 2000)
{
"Type": 2000,
"Delay": 0.0,
"WorldEventObjectFilter": "ResourceCrate_1",
"SustainedEventSlotIndex": 1,
"Count": 1,
"Enabled": true
}
| Field | Description |
|---|---|
Type |
2000 |
WorldEventObjectFilter |
The target crate's name. |
SustainedEventSlotIndex |
0 only enables or disables the crate. 1 also switches the profile to the one whose Index equals Count, and resets the remaining uses to that profile's Limit. |
Count |
Profile Index. Only used when SustainedEventSlotIndex is 1. |
Enabled |
true enables the crate and false disables it. This is applied every time the event fires. |
Delay, Condition, WardenIntel, DialogueID, SoundID and SoundSubtitle work as they do for vanilla events.
A disabled crate cannot be used, and all of its UI turns red. Enabling it again restores its current profile and remaining uses. The event runs locally on every client, as vanilla events do, and the host then syncs the final state.
This works with or without ExtraObjectiveSetup installed. The two plugins do not conflict.
EventsOnUsed
A normal list of warden events. It runs every time the crate's remaining uses go from above 0 to 0. If a profile switch gives the crate new uses and they run out again, the events run again.
Interaction text (TextDataBlock)
All prompt text comes from TextDataBlock, looked up by name. If a block is missing, the built-in fallback is used. The resource crate IDs are the same ones LEGACY's ResourceStation uses, so a text DB that already has them works without changes.
name |
Used for | Fallback |
|---|---|---|
InGame.InteractionPrompt.AmmoStation |
Ammo crate title | AMMUNITION STATION |
InGame.InteractionPrompt.MediStation |
Medi crate title | HEALTH STATION |
InGame.InteractionPrompt.ToolStation |
Tool crate title | TOOL STATION |
InGame.InteractionPrompt.DisinfectionStation |
Disinfect crate title | DISINFECTION STATION |
InGame.OnAdditionalInteractionText.ResourceStation |
Text after the key prompt on resource crates | TO REPLENISH |
InGame.InteractionPrompt.WeaponStation.Swap |
Gear crate title when a swap is possible. {0} is the current gear and {1} is the target gear. |
将 {0} 换为 {1} |
InGame.InteractionPrompt.WeaponStation.CannotSwap |
Gear crate title when no swap is possible | 当前武器无法交换 |
InGame.OnAdditionalInteractionText.WeaponStation |
Text after the key prompt on gear crates | 以交换 |
InGame.OnAdditionalInteractionText.SupplyCrate.Uses |
Remaining uses. {0} is the remaining count and {1} is the profile Limit. Only shown when Limit ≥ 0. |
({0}/{1}) |
Gear names come from the gear's ArchetypeDataBlock.PublicName, so they are localized. Melee and other gear without an archetype use GearCategoryDataBlock.PublicName.
A ready-to-paste set of TextDataBlock entries with English and Simplified Chinese is included as SupplyCrate_TextDataBlock.json. Pick persistentIDs that do not collide with your own text DB.
Examples
1. A medi crate that stays locked until a door opens
Crate:
{
"WorldEventObjectFilter": "MediCrate_B",
"Category": "Resource",
"Enabled": false,
"Position": { "x": 0, "y": 0, "z": 0 },
"ProfileList": [ { "Index": 0, "Type": "Medi", "PackUses": 2, "Limit": 2 } ]
}
In the door's EventsOnDoorOpen:
{ "Type": 2000, "WorldEventObjectFilter": "MediCrate_B", "Enabled": true }
2. One crate that turns into another type
The ammo crate starts on profile 0. When it runs out it switches itself to tool packs (profile 1) after 30 seconds:
{
"WorldEventObjectFilter": "Depot_1",
"Category": "Resource",
"Position": { "x": 0, "y": 0, "z": 0 },
"ProfileList": [
{ "Index": 0, "Type": "Ammo", "PackUses": 3, "Limit": 4 },
{ "Index": 1, "Type": "Tool", "PackUses": 2, "Limit": 2 }
],
"EventsOnUsed": [
{ "Type": 2000, "Delay": 30.0, "WorldEventObjectFilter": "Depot_1",
"SustainedEventSlotIndex": 1, "Count": 1, "Enabled": true }
]
}
When profile 1 is used up as well, the event fires again and switches back to profile 1. The result is a tool-pack crate that refills every 30 seconds.
3. Gear upgrade path
{
"WorldEventObjectFilter": "Armory",
"Category": "Gear",
"Position": { "x": 0, "y": 0, "z": 0 },
"ProfileList": [
{
"Index": 0, "Type": "Map", "Limit": -1,
"GearMap": [
{ "From": "Gear_Pistol_T1", "To": "Gear_Pistol_T2" },
{ "From": "Gear_Pistol_T2", "To": "Gear_Pistol_T3" }
]
}
]
}
Each visit upgrades the held pistol one tier, with no limit. Gear_Pistol_T2 and T3 can be internalEnabled: false, so they only come from the crate.
4. Give everyone the same loadout
{
"Index": 0, "Type": "Uniform", "Limit": 4,
"GearList": [
{ "Slot": "Standard", "To": "Gear_Event_Rifle" },
{ "Slot": "Special", "To": "Gear_Event_Shotgun" },
{ "Slot": "Melee", "To": "Gear_Event_Hammer" },
{ "Slot": "Tool", "To": "Gear_Event_Sentry" }
]
}
Each player swaps the slot they are holding. With Limit: 4, a team of four can swap one slot each, or one player can swap all four.