From a9968c69eed89f47fda2fc9e7e31ce8e6329d9f5 Mon Sep 17 00:00:00 2001 From: kuroppoi <68156848+kuroppoi@users.noreply.github.com> Date: Sun, 30 May 2021 22:46:09 +0200 Subject: [PATCH] Looting & loot tables --- .../gameserver/GameConfiguration.java | 1 + .../java/brainwine/gameserver/GameServer.java | 9 +- .../gameserver/entity/player/Player.java | 42 + .../java/brainwine/gameserver/item/Item.java | 14 + .../gameserver/item/ItemUseType.java | 2 + .../gameserver/item/LootGraphic.java | 22 + .../java/brainwine/gameserver/loot/Loot.java | 46 + .../gameserver/loot/LootManager.java | 79 + gameserver/src/main/resources/loottables.json | 1528 +++++++++++++++++ 9 files changed, 1742 insertions(+), 1 deletion(-) create mode 100644 gameserver/src/main/java/brainwine/gameserver/item/LootGraphic.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/loot/Loot.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/loot/LootManager.java create mode 100644 gameserver/src/main/resources/loottables.json diff --git a/gameserver/src/main/java/brainwine/gameserver/GameConfiguration.java b/gameserver/src/main/java/brainwine/gameserver/GameConfiguration.java index ccee8a1..f5634b0 100644 --- a/gameserver/src/main/java/brainwine/gameserver/GameConfiguration.java +++ b/gameserver/src/main/java/brainwine/gameserver/GameConfiguration.java @@ -42,6 +42,7 @@ public class GameConfiguration { long startTime = System.currentTimeMillis(); logger.info("Loading game configuration ..."); mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE, true); + mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true); LoaderOptions options = new LoaderOptions(); options.setMaxAliasesForCollections(Short.MAX_VALUE); diff --git a/gameserver/src/main/java/brainwine/gameserver/GameServer.java b/gameserver/src/main/java/brainwine/gameserver/GameServer.java index e5cba68..2524adf 100644 --- a/gameserver/src/main/java/brainwine/gameserver/GameServer.java +++ b/gameserver/src/main/java/brainwine/gameserver/GameServer.java @@ -8,6 +8,7 @@ import org.apache.logging.log4j.Logger; import brainwine.gameserver.command.CommandManager; import brainwine.gameserver.entity.player.PlayerManager; +import brainwine.gameserver.loot.LootManager; import brainwine.gameserver.msgpack.MessagePackHelper; import brainwine.gameserver.server.NetworkRegistry; import brainwine.gameserver.server.Server; @@ -21,6 +22,7 @@ public class GameServer { private static GameServer instance; private final Thread handlerThread; private final Queue tasks = new ConcurrentLinkedQueue<>(); + private final LootManager lootManager; private final ZoneManager zoneManager; private final PlayerManager playerManager; private final Server server; @@ -34,8 +36,9 @@ public class GameServer { logger.info("Starting GameServer ..."); CommandManager.init(); GameConfiguration.init(); - StaticZoneGenerator.init(); MessagePackHelper.init(); + lootManager = new LootManager(); + StaticZoneGenerator.init(); zoneManager = new ZoneManager(); playerManager = new PlayerManager(); NetworkRegistry.init(); @@ -99,6 +102,10 @@ public class GameServer { return shutdownRequested; } + public LootManager getLootManager() { + return lootManager; + } + public ZoneManager getZoneManager() { return zoneManager; } diff --git a/gameserver/src/main/java/brainwine/gameserver/entity/player/Player.java b/gameserver/src/main/java/brainwine/gameserver/entity/player/Player.java index f390a37..8ccd049 100644 --- a/gameserver/src/main/java/brainwine/gameserver/entity/player/Player.java +++ b/gameserver/src/main/java/brainwine/gameserver/entity/player/Player.java @@ -2,9 +2,11 @@ package brainwine.gameserver.entity.player; import java.beans.ConstructorProperties; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -24,6 +26,8 @@ import brainwine.gameserver.entity.EntityType; import brainwine.gameserver.entity.FacingDirection; import brainwine.gameserver.item.Item; import brainwine.gameserver.item.ItemRegistry; +import brainwine.gameserver.item.LootGraphic; +import brainwine.gameserver.loot.Loot; import brainwine.gameserver.server.Message; import brainwine.gameserver.server.messages.BlockMetaMessage; import brainwine.gameserver.server.messages.ConfigurationMessage; @@ -525,6 +529,44 @@ public class Player extends Entity implements CommandExecutor { return MathUtils.clamp(skills.getOrDefault(skill, 1), 1, MAX_NATURAL_SKILL_LEVEL); } + public void awardLoot(Loot loot) { + awardLoot(loot, LootGraphic.LOOT); + } + + public void awardLoot(Loot loot, LootGraphic graphic) { + List> notifications = new ArrayList<>(); + + loot.getItems().forEach((item, quantity) -> { + inventory.addItem(item, quantity); + Map notification = new HashMap<>(); + notification.put("item", item.getId()); + notification.put("text", String.format("%s x %s", item.getTitle(), quantity)); + notifications.add(notification); + }); + + Map dialog = new HashMap<>(); + Map section = new HashMap<>(); + section.put("list", notifications); + dialog.put("sections", Arrays.asList(section)); + int crowns = loot.getCrowns(); + + if(crowns > 0) { + addCrowns(crowns); + section.put("text", isV3() ? String.format("%s shiny crowns!", crowns) : String.format("%s shiny crowns!", crowns)); + } + + if(isV3()) { + dialog.put("title", "You found:"); + dialog.put("type", graphic); + sendMessage(new DialogMessage(0, dialog)); + } else { + section.put("title", "You found:"); + section.put("text-color", "ffd95f"); + notify(dialog, NotificationType.REWARD); + sendMessage(new EffectMessage(x, y, "chime", 1)); + } + } + public Inventory getInventory() { return inventory; } diff --git a/gameserver/src/main/java/brainwine/gameserver/item/Item.java b/gameserver/src/main/java/brainwine/gameserver/item/Item.java index 0b3e83e..ec54c9a 100644 --- a/gameserver/src/main/java/brainwine/gameserver/item/Item.java +++ b/gameserver/src/main/java/brainwine/gameserver/item/Item.java @@ -36,6 +36,9 @@ public class Item { @JsonProperty("title") private String title; + @JsonProperty("loot_graphic") + private LootGraphic lootGraphic = LootGraphic.NONE; + @JsonProperty("action") private Action action = Action.NONE; @@ -78,6 +81,9 @@ public class Item { @JsonProperty("crafting quantity") private int craftingQuantity = 1; + @JsonProperty("loot") + private String[] lootCategories = {}; + @JsonProperty("ingredients") private List ingredients = new ArrayList<>(); @@ -128,6 +134,10 @@ public class Item { return id == 0; } + public LootGraphic getLootGraphic() { + return lootGraphic; + } + public Action getAction() { return action; } @@ -200,6 +210,10 @@ public class Item { return decayInventoryItem == null ? this : decayInventoryItem.get(); } + public String[] getLootCategories() { + return lootCategories; + } + public int getCraftingQuantity() { return craftingQuantity; } diff --git a/gameserver/src/main/java/brainwine/gameserver/item/ItemUseType.java b/gameserver/src/main/java/brainwine/gameserver/item/ItemUseType.java index 002f40e..4f905e6 100644 --- a/gameserver/src/main/java/brainwine/gameserver/item/ItemUseType.java +++ b/gameserver/src/main/java/brainwine/gameserver/item/ItemUseType.java @@ -6,9 +6,11 @@ import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; public enum ItemUseType { AFTERBURNER, + CONTAINER, CREATE_DIALOG, DIALOG, CHANGE, + FIELDABLE, FLY, TELEPORT, ZONE_TELEPORT, diff --git a/gameserver/src/main/java/brainwine/gameserver/item/LootGraphic.java b/gameserver/src/main/java/brainwine/gameserver/item/LootGraphic.java new file mode 100644 index 0000000..39ca18a --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/item/LootGraphic.java @@ -0,0 +1,22 @@ +package brainwine.gameserver.item; + +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; + +import brainwine.gameserver.msgpack.EnumValue; +import brainwine.gameserver.msgpack.RegisterEnum; + +@RegisterEnum +public enum LootGraphic { + + LOOT, + LOOT_RED, + LOOT_MECH, + + @JsonEnumDefaultValue + NONE; + + @EnumValue + public String getId() { + return toString().toLowerCase(); + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/loot/Loot.java b/gameserver/src/main/java/brainwine/gameserver/loot/Loot.java new file mode 100644 index 0000000..5b61576 --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/loot/Loot.java @@ -0,0 +1,46 @@ +package brainwine.gameserver.loot; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import brainwine.gameserver.item.Item; +import brainwine.gameserver.zone.Biome; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Loot { + + @JsonProperty("items") + private Map items = new HashMap<>(); + + @JsonProperty("crowns") + private int crowns; + + @JsonProperty("frequency") + private int frequency = 1; + + @JsonProperty("biome") + private Biome biome; + + @JsonCreator + private Loot() {} + + public Map getItems() { + return items; + } + + public int getCrowns() { + return crowns; + } + + public int getFrequency() { + return frequency; + } + + public Biome getBiome() { + return biome; + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/loot/LootManager.java b/gameserver/src/main/java/brainwine/gameserver/loot/LootManager.java new file mode 100644 index 0000000..0de23b4 --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/loot/LootManager.java @@ -0,0 +1,79 @@ +package brainwine.gameserver.loot; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import brainwine.gameserver.util.WeightedList; +import brainwine.gameserver.zone.Biome; + +public class LootManager { + + private static final Logger logger = LogManager.getLogger(); + private final Map> lootTables = new HashMap<>(); + + public LootManager() { + loadLootTables(); + } + + private void loadLootTables() { + logger.info("Loading loot tables ..."); + ObjectMapper mapper = new ObjectMapper(); + File file = new File("loottables.json"); + + try { + if(!file.exists()) { + Files.copy(LootManager.class.getResourceAsStream("/loottables.json"), file.toPath()); + } + + Map> loot = mapper.readValue(file, new TypeReference>>(){}); + lootTables.putAll(loot); + } catch (IOException e) { + logger.error("Failed to load loot tables", e); + } + } + + public List getLootTable(String category) { + return lootTables.getOrDefault(category, Collections.emptyList()); + } + + public List getEligibleLoot(int level, Biome biome, String... categories) { + List eligibleLoot = new ArrayList<>(); + + for(String category : categories) { + eligibleLoot.addAll(getLootTable(category)); + } + + eligibleLoot.removeIf(loot -> loot.getBiome() != null && loot.getBiome() != biome); + + if(Math.random() > level * 0.015) { + int[] frequencies = {18, 15, 12, 9, 7, 5, 4, 3, 2}; + int minFrequency = level > frequencies.length ? 1 : frequencies[level - 1]; + eligibleLoot.removeIf(loot -> loot.getFrequency() < minFrequency); + } + + return eligibleLoot; + } + + public Loot getRandomLoot(int level, Biome biome, String... categories) { + WeightedList weightedLoot = new WeightedList<>(); + List eligibleLoot = getEligibleLoot(level, biome, categories); + + for(Loot loot : eligibleLoot) { + weightedLoot.addEntry(loot, loot.getFrequency()); + } + + return weightedLoot.next(); + } +} diff --git a/gameserver/src/main/resources/loottables.json b/gameserver/src/main/resources/loottables.json new file mode 100644 index 0000000..83ddaa2 --- /dev/null +++ b/gameserver/src/main/resources/loottables.json @@ -0,0 +1,1528 @@ +{ + "resources": [ + { + "items": { + "building/wood": 15, + "building/wood-board": 5 + }, + "frequency": 200 + }, + { + "items": { + "ground/copper-ore": 15, + "ground/zinc-ore": 5 + }, + "frequency": 160 + }, + { + "items": { + "ground/zinc-ore": 10 + }, + "frequency": 150 + }, + { + "items": { + "ground/clay": 15 + }, + "frequency": 160 + }, + { + "items": { + "ground/iron-ore": 10, + "building/iron": 5 + }, + "frequency": 120 + }, + { + "items": { + "back/paper": 20 + }, + "frequency": 80 + }, + { + "items": { + "ground/quartz-ore": 10, + "ground/lead-ore": 5 + }, + "frequency": 60 + }, + { + "items": { + "ground/lead-ore": 10, + "ground/iron-ore": 5 + }, + "frequency": 60 + }, + { + "items": { + "back/glass": 15 + }, + "frequency": 60 + }, + { + "items": { + "back/glass-divided": 15 + }, + "frequency": 50 + }, + { + "items": { + "building/brass": 10, + "building/iron": 10, + "building/copper": 10 + }, + "frequency": 40 + }, + { + "items": { + "mechanical/pipe": 20 + }, + "frequency": 20 + }, + { + "items": { + "ground/marble-ore": 10 + }, + "frequency": 20 + }, + { + "items": { + "ground/bloodstone-ore": 10 + }, + "frequency": 10 + }, + { + "items": { + "ground/salt": 5, + "ground/fire-salt": 1 + }, + "frequency": 15 + }, + { + "items": { + "building/plug": 5 + }, + "frequency": 50 + } + ], + "treasure": [ + { + "items": { + "vegetation/pumpkin-seeds": 2 + }, + "frequency": 15 + }, + { + "items": { + "vegetation/flower-coxcomb-bulb": 3 + }, + "frequency": 50 + }, + { + "items": { + "vegetation/flower-amaryllis-bulb": 2 + }, + "frequency": 30 + }, + { + "items": { + "vegetation/flower-asphodelus-bulb": 2 + }, + "frequency": 15 + }, + { + "items": { + "vegetation/flower-birds-foot-trefoil-bulb": 1 + }, + "frequency": 9 + }, + { + "items": { + "vegetation/flower-carnations-bulb": 4 + }, + "frequency": 40 + }, + { + "items": { + "vegetation/flower-tuberose-bulb": 3 + }, + "frequency": 15 + }, + { + "items": { + "vegetation/flower-echinacea-bulb": 1 + }, + "frequency": 15 + }, + { + "items": { + "vegetation/flower-sunflower-bulb": 1 + }, + "frequency": 12 + }, + { + "items": { + "vegetation/flower-cactus-bulb": 1 + }, + "frequency": 10 + }, + { + "items": { + "vegetation/flower-bird-of-paradise-bulb": 1 + }, + "frequency": 8 + }, + { + "items": { + "vegetation/flower-trumpets-bulb": 1 + }, + "frequency": 5 + }, + { + "items": { + "vegetation/tree-hellish-bulb": 1 + }, + "frequency": 1 + }, + { + "items": { + "vegetation/tree-bonsai-bulb": 1 + }, + "frequency": 2 + }, + { + "items": { + "furniture/daguerreotype-small": 1 + }, + "frequency": 15 + }, + { + "items": { + "furniture/painting-landscape": 1 + }, + "frequency": 10 + }, + { + "items": { + "building/gargoyle-falcon-side": 2 + }, + "frequency": 25 + }, + { + "items": { + "signs/plaque": 1 + }, + "frequency": 20 + }, + { + "items": { + "ground/fire-salt": 5 + }, + "frequency": 20 + }, + { + "items": { + "ground/earth-compost": 10 + }, + "frequency": 20 + }, + { + "items": { + "accessories/battery": 4 + }, + "frequency": 25 + }, + { + "items": { + "ground/fire-salt": 2, + "ground/ectoplasm": 2 + }, + "frequency": 20 + }, + { + "items": { + "consumables/teleporter": 2 + }, + "frequency": 15 + }, + { + "items": { + "mechanical/beacon": 1, + "mechanical/teleporter-mini": 1 + }, + "frequency": 12 + }, + { + "items": { + "ground/crystal-blue-1": 2 + }, + "frequency": 12 + }, + { + "items": { + "building/crystal-blue": 2 + }, + "frequency": 9 + }, + { + "items": { + "building/crystal-red": 1 + }, + "frequency": 6 + }, + { + "items": { + "bulding/crystal-purple": 1 + }, + "frequency": 6 + }, + { + "items": { + "mechanical/bomb-dig": 2 + }, + "frequency": 10 + }, + { + "items": { + "consumables/teleporter": 2 + }, + "frequency": 4 + }, + { + "items": { + "building/statue-gothic-front": 1 + }, + "frequency": 9 + }, + { + "items": { + "building/statue-gothic-side": 1 + }, + "frequency": 7 + }, + { + "items": { + "tools/net": 1, + "accessories/shillings": 10 + }, + "frequency": 15 + }, + { + "items": { + "accessories/sprocket": 1 + }, + "frequency": 15 + }, + { + "items": { + "accessories/widget": 1 + }, + "frequency": 15 + }, + { + "items": { + "accessories/flashlight-brass": 1 + }, + "frequency": 15 + }, + { + "items": { + "accessories/compressor-basic": 1 + }, + "frequency": 10 + }, + { + "items": { + "accessories/program": 1 + }, + "frequency": 9 + }, + { + "items": { + "accessories/memory": 1 + }, + "frequency": 8 + }, + { + "items": { + "accessories/schematic": 1 + }, + "frequency": 8 + }, + { + "items": { + "furniture/companion-cube": 1 + }, + "frequency": 5 + }, + { + "items": { + "accessories/key-skeleton": 1 + }, + "frequency": 5 + }, + { + "items": { + "accessories/glove": 1 + }, + "frequency": 4 + }, + { + "items": { + "accessories/army-knife": 1 + }, + "frequency": 5 + }, + { + "items": { + "accessories/clover": 1 + }, + "frequency": 3 + }, + { + "items": { + "accessories/seashell": 1 + }, + "frequency": 4 + }, + { + "items": { + "accessories/stopwatch": 1 + }, + "frequency": 5 + } + ], + "treasure+": [ + { + "crowns": 10, + "frequency": 25 + }, + { + "crowns": 20, + "frequency": 12 + }, + { + "crowns": 50, + "frequency": 6 + }, + { + "items": { + "furniture/painting-autumn": 1 + }, + "frequency": 3 + }, + { + "items": { + "vegetation/flower-tuberose-bulb": 2, + "vegetation/flower-amaryllis-bulb": 3 + }, + "frequency": 25 + }, + { + "items": { + "vegetation/flower-asphodelus-bulb": 2, + "vegetation/flower-carnations-bulb": 3 + }, + "frequency": 20 + }, + { + "items": { + "vegetation/pumpkin-seeds": 3 + }, + "frequency": 15 + }, + { + "items": { + "vegetation/flower-lobelia-bulb": 2 + }, + "frequency": 10 + }, + { + "items": { + "vegetation/flower-lobelia-bulb": 2, + "vegetation/flower-birds-foot-trefoil-bulb": 1 + }, + "frequency": 8 + }, + { + "items": { + "vegetation/flower-delphinium-bulb": 1 + }, + "frequency": 5 + }, + { + "items": { + "vegetation/flower-echinacea-bulb": 2 + }, + "frequency": 15 + }, + { + "items": { + "vegetation/flower-sunflower-bulb": 2 + }, + "frequency": 12 + }, + { + "items": { + "vegetation/flower-cactus-bulb": 1 + }, + "frequency": 10 + }, + { + "items": { + "vegetation/flower-bird-of-paradise-bulb": 1 + }, + "frequency": 8 + }, + { + "items": { + "vegetation/flower-trumpets-bulb": 1 + }, + "frequency": 7 + }, + { + "items": { + "vegetation/tree-hellish-bulb": 1 + }, + "frequency": 2 + }, + { + "items": { + "vegetation/tree-bonsai-bulb": 1 + }, + "frequency": 4 + }, + { + "items": { + "furniture/daguerreotype-small": 1 + }, + "frequency": 30 + }, + { + "items": { + "furniture/painting-landscape": 1 + }, + "frequency": 20 + }, + { + "items": { + "furniture/map": 1 + }, + "frequency": 18 + }, + { + "items": { + "mechanical/typewriter": 1 + }, + "frequency": 17 + }, + { + "items": { + "accessories/sprocket": 1 + }, + "frequency": 15 + }, + { + "items": { + "accessories/widget": 1 + }, + "frequency": 15 + }, + { + "items": { + "mechanical/inhibitor": 1 + }, + "frequency": 15 + }, + { + "items": { + "furniture/easel": 1 + }, + "frequency": 14 + }, + { + "items": { + "furniture/ship-in-bottle": 1 + }, + "frequency": 12 + }, + { + "items": { + "mechanical/ship-wheel": 1 + }, + "frequency": 12 + }, + { + "items": { + "furniture/head-fish": 1 + }, + "frequency": 10 + }, + { + "items": { + "furniture/daguerreotype-large": 1 + }, + "frequency": 10 + }, + { + "items": { + "furniture/globe": 1 + }, + "frequency": 9 + }, + { + "items": { + "furniture/easel-tall": 1 + }, + "frequency": 8 + }, + { + "items": { + "furniture/marionette": 1 + }, + "frequency": 7 + }, + { + "items": { + "mechanical/telescope": 1 + }, + "frequency": 6 + }, + { + "items": { + "furniture/moon": 1 + }, + "biome": "space", + "frequency": 5 + }, + { + "items": { + "furniture/mars": 1 + }, + "biome": "desert", + "frequency": 5 + }, + { + "items": { + "furniture/airship-in-bottle": 1 + }, + "frequency": 3 + }, + { + "items": { + "solar-system-diorama": 1 + }, + "frequency": 1 + }, + { + "items": { + "signs/plaque-landmark": 1 + }, + "frequency": 5 + }, + { + "items": { + "furniture/stuffed-bear": 1 + }, + "frequency": 18 + }, + { + "items": { + "furniture/stuffed-crow": 1 + }, + "frequency": 14 + }, + { + "items": { + "furniture/stuffed-android": 1 + }, + "frequency": 10 + }, + { + "items": { + "furniture/stuffed-terrapus": 1 + }, + "frequency": 8 + }, + { + "items": { + "furniture/stuffed-snowman": 1 + }, + "frequency": 7 + }, + { + "items": { + "furniture/stuffed-panda": 1 + }, + "frequency": 6 + }, + { + "items": { + "furniture/stuffed-squid": 1 + }, + "frequency": 5 + }, + { + "items": { + "furniture/stuffed-cthulhu": 1 + }, + "frequency": 4 + }, + { + "items": { + "furniture/stuffed-brain": 1 + }, + "frequency": 3 + }, + { + "items": { + "furniture/pinned-cockroach": 1 + }, + "frequency": 18 + }, + { + "items": { + "furniture/pinned-scorpion": 1 + }, + "frequency": 14 + }, + { + "items": { + "furniture/pinned-beetle": 1 + }, + "frequency": 10 + }, + { + "items": { + "furniture/pinned-bee": 1 + }, + "frequency": 8 + }, + { + "items": { + "furniture/pinned-dragonfly": 1 + }, + "frequency": 6 + }, + { + "items": { + "furniture/pinned-millipede": 1 + }, + "frequency": 3 + }, + { + "items": { + "furniture/pinned-tarantula": 1 + }, + "frequency": 2 + }, + { + "items": { + "furniture/pinned-preying-mantis": 1 + }, + "frequency": 1 + }, + { + "items": { + "holiday/cornucopia": 1 + }, + "frequency": 6 + }, + { + "items": { + "holiday/gingerbread-house": 1 + }, + "frequency": 2 + }, + { + "items": { + "holiday/holly-garland": 1 + }, + "frequency": 10 + }, + { + "items": { + "holiday/mistletoe": 1 + }, + "frequency": 6 + }, + { + "items": { + "holiday/gift-small": 2 + }, + "frequency": 12 + }, + { + "items": { + "holiday/gift-tall": 1 + }, + "frequency": 6 + }, + { + "items": { + "holiday/christmas-lights-white": 6 + }, + "frequency": 8 + }, + { + "items": { + "holiday/christmas-lights-reindeer": 1 + }, + "frequency": 10 + }, + { + "items": { + "holiday/christmas-lights-sleigh": 1 + }, + "frequency": 5 + }, + { + "items": { + "holiday/tree-charlie-brown": 1 + }, + "frequency": 2 + }, + { + "items": { + "holiday/sleigh": 1 + }, + "frequency": 1 + }, + { + "items": { + "building/statue-figurine-1": 1 + }, + "frequency": 12 + }, + { + "items": { + "building/statue-figurine-2": 1 + }, + "frequency": 10 + }, + { + "items": { + "building/statue-figurine-3": 1 + }, + "frequency": 8 + }, + { + "items": { + "building/statue-figurine-large-1": 1 + }, + "frequency": 5 + }, + { + "items": { + "building/statue-figurine-large-2": 1 + }, + "frequency": 5 + }, + { + "items": { + "building/statue-figurine-large-3": 1 + }, + "frequency": 5 + }, + { + "items": { + "building/statue-figurine-large-4": 1 + }, + "frequency": 3 + }, + { + "items": { + "mechanical/friend-parts-gear": 1, + "mechanical/friend-parts-boxing-gloves": 1 + }, + "frequency": 3 + }, + { + "items": { + "mechanical/friend-parts-joint": 2, + "mechanical/friend-parts-scissors": 1 + }, + "frequency": 3 + }, + { + "items": { + "mechanical/friend-parts-gear": 4 + }, + "frequency": 5 + }, + { + "items": { + "mechanical/friend-parts-joint": 1, + "mechanical/friend-parts-foot": 2 + }, + "frequency": 3 + }, + { + "items": { + "mechanical/friend-parts-key": 1, + "mechanical/friend-parts-gear": 2 + }, + "frequency": 3 + }, + { + "items": { + "mechanical/friend-parts-head": 1 + }, + "frequency": 3 + }, + { + "items": { + "mechanical/bomb-dig": 3 + }, + "frequency": 20 + }, + { + "items": { + "mechanical/science-scrap": 1 + }, + "frequency": 18 + }, + { + "items": { + "mechanical/chemistry-set": 1 + }, + "frequency": 12 + }, + { + "items": { + "mechanical/chemistry-set": 1, + "mechanical/science-scrap": 1 + }, + "frequency": 7 + }, + { + "items": { + "mechanical/science-bulb": 1 + }, + "frequency": 7 + }, + { + "items": { + "mechanical/science-gadget": 1 + }, + "frequency": 3 + }, + { + "items": { + "mechanical/bomb-spawner": 2 + }, + "frequency": 15 + }, + { + "items": { + "mechanical/bomb-spawner-large": 1 + }, + "frequency": 8 + }, + { + "items": { + "mechanical/beacon": 1, + "mechanical/teleporter-mini": 1 + }, + "frequency": 10 + }, + { + "items": { + "mechanical/teleporter-mini-diamond": 1 + }, + "frequency": 4 + }, + { + "items": { + "accessories/schematic": 1 + }, + "frequency": 13 + }, + { + "items": { + "accessories/program": 1 + }, + "frequency": 14 + }, + { + "items": { + "accessories/memory": 1 + }, + "frequency": 13 + }, + { + "items": { + "containers/fertilizer": 2 + }, + "frequency": 10 + }, + { + "items": { + "containers/pandora": 1 + }, + "frequency": 6 + }, + { + "items": { + "consumables/teleporter": 3 + }, + "frequency": 6 + }, + { + "items": { + "lighting/fancy-lamp-1": 1 + }, + "frequency": 15 + }, + { + "items": { + "lighting/fancy-lamp-2": 1 + }, + "frequency": 15 + }, + { + "items": { + "lighting/fancy-lamp-7": 1 + }, + "frequency": 10 + }, + { + "items": { + "lighting/fancy-lamp-6": 1 + }, + "frequency": 8 + }, + { + "items": { + "lighting/fancy-lamp-4": 1 + }, + "frequency": 5 + }, + { + "items": { + "lighting/fancy-lamp-3": 1 + }, + "frequency": 3 + }, + { + "items": { + "lighting/fancy-lamp-5": 1 + }, + "frequency": 1 + }, + { + "items": { + "mechanical/compass": 1 + }, + "frequency": 3 + }, + { + "items": { + "mechanical/compass-burned": 1 + }, + "frequency": 2 + }, + { + "items": { + "mechanical/compass-icy": 1 + }, + "frequency": 2 + }, + { + "items": { + "mechanical/compass-sandy": 1 + }, + "frequency": 2 + }, + { + "items": { + "mechanical/compass-dark": 1 + }, + "frequency": 2 + }, + { + "items": { + "ground/fire-salt": 6 + }, + "frequency": 15 + }, + { + "items": { + "accessories/battery": 6 + }, + "frequency": 20 + }, + { + "items": { + "building/crystal-red": 2 + }, + "frequency": 6 + }, + { + "items": { + "building/crystal-purple": 2 + }, + "frequency": 6 + }, + { + "items": { + "ground/crystal-red-1": 1 + }, + "frequency": 5 + }, + { + "items": { + "ground/crystal-purple-1": 1 + }, + "frequency": 4 + }, + { + "items": { + "accessories/glove": 1 + }, + "frequency": 4 + }, + { + "items": { + "accessories/army-knife": 1 + }, + "frequency": 5 + }, + { + "items": { + "accessories/clover": 1 + }, + "frequency": 3 + }, + { + "items": { + "accessories/seashell": 1 + }, + "frequency": 4 + }, + { + "items": { + "accessories/stopwatch": 1 + }, + "frequency": 5 + }, + { + "items": { + "accessories/agility-brass": 1 + }, + "frequency": 5 + }, + { + "items": { + "accessories/scope-brass": 1 + }, + "frequency": 5 + }, + { + "items": { + "accessories/rake": 1 + }, + "frequency": 5 + }, + { + "items": { + "accessories/flashlight-diamond": 1 + }, + "frequency": 4 + }, + { + "items": { + "accessories/pocketwatch": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/horseshoe": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/sand-dollar": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/army-knife-diamond": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/glove-diamond": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/agility-diamond": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/scope-diamond": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/rake-diamond": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/key-skeleton": 1 + }, + "frequency": 10 + }, + { + "items": { + "holiday/coffin": 1 + }, + "frequency": 7 + }, + { + "items": { + "vegetation/pumpkin-giant": 1 + }, + "frequency": 7 + }, + { + "items": { + "vegetation/pine-tree-festive-giant": 1 + }, + "frequency": 6 + }, + { + "items": { + "ground/terrapus-pet-egg": 1 + }, + "frequency": 6 + }, + { + "items": { + "furniture/companion-cube": 1 + }, + "frequency": 5 + }, + { + "items": { + "containers/cat": 1 + }, + "frequency": 4 + }, + { + "items": { + "containers/dog": 1 + }, + "frequency": 4 + }, + { + "items": { + "containers/android": 1 + }, + "frequency": 2 + }, + { + "items": { + "tools/net-diamond": 1 + }, + "frequency": 2 + }, + { + "items": { + "tools/hatchet-diamond": 1 + }, + "frequency": 2 + }, + { + "items": { + "tools/spade-diamond": 1 + }, + "frequency": 2 + }, + { + "items": { + "mechanical/dish-micro": 1 + }, + "frequency": 4 + }, + { + "items": { + "consumables/book-skill": 1 + }, + "frequency": 1 + }, + { + "items": { + "consumables/world-key": 1 + }, + "frequency": 1 + }, + { + "items": { + "mechanical/dish": 1 + }, + "frequency": 2 + }, + { + "items": { + "accessories/shillings": 10 + }, + "frequency": 20 + }, + { + "items": { + "accessories/shillings": 25 + }, + "frequency": 10 + }, + { + "items": { + "accessories/shillings": 50 + }, + "frequency": 5 + }, + { + "items": { + "accessories/shillings": 250 + }, + "frequency": 1 + } + ], + "armaments": [ + { + "items": { + "consumables/jerky-power": 2, + "consumables/jerky": 6 + }, + "frequency": 70 + }, + { + "items": { + "consumables/canister": 4 + }, + "frequency": 60 + }, + { + "items": { + "consumables/jerky": 4, + "consumables/canister": 4 + }, + "frequency": 40 + }, + { + "items": { + "consumables/cloak": 1, + "consumables/canister": 2 + }, + "frequency": 30 + }, + { + "items": { + "ammo/gunpowder": 5, + "ammo/bullets": 5 + }, + "frequency": 80 + }, + { + "items": { + "mechanical/spikes": 5 + }, + "frequency": 30 + }, + { + "items": { + "ground/terrapus-egg": 3 + }, + "frequency": 20 + }, + { + "items": { + "consumables/filet": 3 + }, + "frequency": 20 + }, + { + "items": { + "ammo/gunpowder": 10, + "consumables/canister": 3 + }, + "frequency": 30 + }, + { + "items": { + "consumables/tea": 2 + }, + "frequency": 20 + }, + { + "items": { + "ammo/gunpowder": 10 + }, + "frequency": 20 + }, + { + "items": { + "mechanical/bomb-incendiary": 2 + }, + "frequency": 40 + }, + { + "items": { + "mechanical/bomb-electric": 2 + }, + "frequency": 32 + }, + { + "items": { + "mechanical/bomb": 3 + }, + "frequency": 24 + }, + { + "items": { + "mechanical/trap-mine": 3 + }, + "frequency": 25 + }, + { + "items": { + "mechanical/turret-pistol": 1 + }, + "frequency": 32 + } + ], + "armaments+": [ + { + "items": { + "consumables/jerky-power": 10 + }, + "frequency": 40 + }, + { + "items": { + "consumables/jerky-power": 5, + "consumables/canister": 5 + }, + "frequency": 30 + }, + { + "items": { + "ammo/gunpowder": 25 + }, + "frequency": 20 + }, + { + "items": { + "consumables/cloak": 2 + }, + "frequency": 16 + }, + { + "items": { + "consumables/filet-fire": 3, + "consumables/cloak": 1, + "consumables/teleporter": 1 + }, + "frequency": 15 + }, + { + "items": { + "mechanical/bomb-large": 1, + "mechanical/bomb": 5 + }, + "frequency": 20 + }, + { + "items": { + "mechanical/trap-mine": 3, + "mechanical/bomb-large": 2 + }, + "frequency": 12 + }, + { + "items": { + "mechanical/bomb-electric": 2, + "mechanical/bomb-incendiary": 3 + }, + "frequency": 10 + }, + { + "items": { + "ground/terrapus-egg-large": 1, + "ground/terrapus-egg": 5 + }, + "frequency": 15 + }, + { + "items": { + "mechanical/turret-fire": 1 + }, + "frequency": 20 + }, + { + "items": { + "mechanical/turret-acid": 1 + }, + "frequency": 12 + }, + { + "items": { + "mechanical/turret-flame": 1 + }, + "frequency": 10 + }, + { + "items": { + "mechanical/turret-dessicator": 1 + }, + "frequency": 8 + }, + { + "items": { + "mechanical/bomb-water": 1 + }, + "frequency": 6 + }, + { + "items": { + "mechanical/bomb-acid": 1 + }, + "frequency": 5 + }, + { + "items": { + "mechanical/bomb-lava": 1 + }, + "frequency": 5 + }, + { + "items": { + "shields/acid": 1 + }, + "frequency": 4 + }, + { + "items": { + "tools/gun-energy-pistol": 1 + }, + "frequency": 2 + }, + { + "items": { + "mechanical/spawner-small": 1 + }, + "frequency": 1 + } + ] +} \ No newline at end of file