/**
Copyright (C) <2015> <coolAlias>
This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such,
you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package zeldaswordskills.world.gen;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import net.minecraft.init.Items;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.Vec3i;
import net.minecraft.util.WeightedRandomChestContent;
import net.minecraft.world.World;
import net.minecraftforge.common.ChestGenHooks;
import zeldaswordskills.api.block.IHookable.HookshotType;
import zeldaswordskills.api.block.IWhipBlock;
import zeldaswordskills.api.entity.BombType;
import zeldaswordskills.item.ItemBrokenSword;
import zeldaswordskills.item.ItemHookShotUpgrade.UpgradeType;
import zeldaswordskills.item.ItemInstrument.Instrument;
import zeldaswordskills.item.ItemKeyBig;
import zeldaswordskills.item.ZSSItems;
import zeldaswordskills.ref.Config;
import zeldaswordskills.ref.LibPotionID;
import zeldaswordskills.skills.SkillBase;
import zeldaswordskills.util.WorldUtils;
import zeldaswordskills.world.gen.structure.RoomBase;
import zeldaswordskills.world.gen.structure.RoomBoss;
/**
*
* Thanks to FatherToast for his tips on registering chests with Forge.
*
*/
public class DungeonLootLists
{
/**
* Adds all weighted contents to the specified category, setting minimum and
* maximum number of items that can generate in this chest category
*/
public static void setCategoryStats(ChestGenHooks category, int min, int max, WeightedRandomChestContent[] contents) {
category.setMin(min);
category.setMax(max);
for (WeightedRandomChestContent item : contents) {
category.addItem(item);
}
}
/** Items version: Creates a weighted chest content for a generic item with the min, max, and weight */
public static WeightedRandomChestContent getLoot(Item item, int min, int max, int weight) {
return new WeightedRandomChestContent(new ItemStack(item), min, max, weight);
}
/** Items with damage version: Creates a weighted chest content with the min, max, and weight */
public static WeightedRandomChestContent getLoot(Item item, int damage, int min, int max, int weight) {
return new WeightedRandomChestContent(new ItemStack(item, 1, damage), min, max, weight);
}
/** Itemstack version: Creates a weighted chest content with the min, max, and weight */
public static WeightedRandomChestContent getLoot(ItemStack stack, int min, int max, int weight) {
return new WeightedRandomChestContent(stack, min, max, weight);
}
public static String
/** Standard loot that appears in all chests */
BASIC_LOOT = "zss.basic_chest_loot",
BOSS_LOOT = "zss.boss_chest_loot",
/** Loot table to use for non-special (e.g. ocean, lava, etc.) chests */
DEFAULT_LOOT = "zss.default_chest_loot",
JAR_DROPS = "zss.jar_drops",
LAVA_LOOT = "zss.lava_chest_loot",
LOCKED_LOOT = "zss.locked_chest_loot",
MOUNTAIN_LOOT = "zss.mountain_chest_loot",
NETHER_LOOT = "zss.nether_chest_loot",
OCEAN_LOOT = "zss.ocean_chest_loot";
/** List of droppable skill orb items as weighted chest contents, not including the bonus heart */
private static List<WeightedRandomChestContent> skillOrbLootList;
/**
* Initializes all of the loot tables for dungeon generation
*/
public static void init() {
initBasicConsumables();
initBossLoot();
initDefaultLoot();
initJarDrops();
initLavaLoot();
initLockedLoot();
initMountainLoot();
initNetherLoot();
initOceanLoot();
initSkillOrbLoot();
}
/**
* Generates the chest contents for non-boss secret rooms, adding appropriate location-based items and locked chest loot
*/
public static void generateChestContents(World world, Random rand, IInventory chest, RoomBase room, boolean isLockedChest) {
ChestGenHooks info = ChestGenHooks.getInfo(BASIC_LOOT);
WeightedRandomChestContent.generateChestContents(rand, info.getItems(rand), chest, info.getCount(rand));
int n = rand.nextInt(3);
if (n > 0 && (isLockedChest || rand.nextInt(4) == 0)) {
if (room.inLava) {
WeightedRandomChestContent.generateChestContents(rand, ChestGenHooks.getInfo(LAVA_LOOT).getItems(rand), chest, n);
} else if (room.inOcean) {
WeightedRandomChestContent.generateChestContents(rand, ChestGenHooks.getInfo(OCEAN_LOOT).getItems(rand), chest, n);
} else if (room.inMountain) {
WeightedRandomChestContent.generateChestContents(rand, ChestGenHooks.getInfo(MOUNTAIN_LOOT).getItems(rand), chest, n);
} else {
WeightedRandomChestContent.generateChestContents(rand, ChestGenHooks.getInfo(DEFAULT_LOOT).getItems(rand), chest, n);
}
}
if (room.inNether) {
info = ChestGenHooks.getInfo(NETHER_LOOT);
WorldUtils.generateRandomChestContents(rand, info.getItems(rand), chest, info.getCount(rand), true);
}
if (isLockedChest) {
info = ChestGenHooks.getInfo(LOCKED_LOOT);
WeightedRandomChestContent.generateChestContents(rand, info.getItems(rand), chest, info.getCount(rand));
if (!(room instanceof RoomBoss)) {
if (rand.nextFloat() < Config.getRandomBossItemChance()) {
WorldUtils.addItemToInventoryAtRandom(rand, ChestGenHooks.getInfo(BOSS_LOOT).getOneItem(rand), chest, 3);
}
if (rand.nextInt(20) < Config.getBigKeyWeight()) {
Vec3i center = room.getBoundingBox().getCenter();
ItemStack key = ItemKeyBig.getKeyForBiome(world, new BlockPos(center));
if (key != null) {
WorldUtils.addItemToInventoryAtRandom(rand, key, chest, 3);
} else { // non-temple biomes should still give something nice
WorldUtils.addItemToInventoryAtRandom(rand, ChestGenHooks.getInfo(BOSS_LOOT).getOneItem(rand), chest, 3);
}
}
}
}
}
/**
* Generates a random number of items plus special boss chest loot
*/
public static void generateBossChestContents(World world, Random rand, IInventory chest, RoomBoss room) {
generateChestContents(world, rand, chest, room, true);
ChestGenHooks info = ChestGenHooks.getInfo(BOSS_LOOT);
WeightedRandomChestContent.generateChestContents(rand, info.getItems(rand), chest, info.getCount(rand));
WorldUtils.addItemToInventoryAtRandom(rand, new ItemStack(ZSSItems.heartPiece), chest, 3);
// special items that always generate, i.e. the Pendants of Virtue
ItemStack stack = room.getBossType().getSpecialItem();
if (stack != null) {
WorldUtils.addItemToInventoryAtRandom(rand, stack, chest, 3);
}
// possibly select a random special item from the boss type's list
stack = room.getBossType().getRandomSpecialItem(rand);
if (stack != null && rand.nextFloat() < 0.2F) {
WorldUtils.addItemToInventoryAtRandom(rand, stack, chest, 3);
} else {
WorldUtils.generateRandomChestContents(rand, skillOrbLootList, chest, 1, false);
}
}
private static void initBasicConsumables() {
setCategoryStats(ChestGenHooks.getInfo(BASIC_LOOT), Config.getMinNumItems(), Config.getMinNumItems() + 4, new WeightedRandomChestContent[] {
getLoot(Items.apple, 1, 2, 3),
getLoot(Items.golden_apple, 1, 1, 1),
getLoot(Items.bread, 1, 2, 3),
getLoot(Items.bucket, 1, 1, 1),
getLoot(Items.compass, 1, 1, 2),
getLoot(Items.map, 1, 2, 2),
getLoot(Items.experience_bottle, 1, 5, 2),
getLoot(Items.name_tag, 1, 2, 2),
getLoot(Items.diamond, 1, 2, 1),
getLoot(Items.gold_ingot, 1, 2, 2),
getLoot(Items.iron_ingot, 1, 2, 3),
getLoot(Items.leather, 1, 3, 3),
getLoot(Items.glass_bottle, 1, 2, 3),
getLoot(Items.emerald, 2, 5, 5),
getLoot(Items.arrow, 3, 7, 5),
getLoot(Items.melon_seeds, 1, 3, 2),
getLoot(Items.pumpkin_seeds, 1, 3, 2),
getLoot(ZSSItems.dekuNut, 1, 3, 2),
getLoot(ZSSItems.bomb, BombType.BOMB_STANDARD.ordinal(), 1, 2, Config.getBombWeight()),
getLoot(ZSSItems.bombBag, 1, 1, (Config.getBombBagWeight() > 5 ? 2 : 1)),
getLoot(ZSSItems.keySmall, 1, 1, Config.getSmallKeyWeight()),
getLoot(ZSSItems.potionRed, 1, 1, 3),
getLoot(ZSSItems.potionGreen, 1, 1, 1),
getLoot(ZSSItems.potionPurple, 1, 1, 1),
getLoot(ZSSItems.shieldDeku, 1, 1, 1),
getLoot(ItemBrokenSword.getBrokenSwordFor(ZSSItems.swordKokiri), 1, 1, 1)
});
}
private static void initBossLoot() {
setCategoryStats(ChestGenHooks.getInfo(BOSS_LOOT), 1, 2, new WeightedRandomChestContent[] {
getLoot(ZSSItems.arrowFire, 7, 15, 1),
getLoot(ZSSItems.arrowIce, 7, 15, 1),
getLoot(ZSSItems.arrowLight, 3, 7, 1),
getLoot(ZSSItems.bombBag, 1, 1, 1),
getLoot(ZSSItems.boomerang, 1, 1, 2),
getLoot(ZSSItems.bootsHeavy, 1, 1, 1),
getLoot(ZSSItems.bootsHover, 1, 1, 1),
getLoot(ZSSItems.bootsPegasus, 1, 1, 1),
getLoot(ZSSItems.bootsRubber, 1, 1, 1),
getLoot(ZSSItems.crystalSpirit, 1, 1, 1),
getLoot(ZSSItems.dekuLeaf, 1, 1, 1),
getLoot(Items.golden_apple, 1, 1, 1, 1), // enchanted golden apple
getLoot(ZSSItems.hammer, 1, 1, 2),
getLoot(ZSSItems.heroBow, 1, 1, 2),
getLoot(ZSSItems.hookshot, HookshotType.WOOD_SHOT.ordinal(), 1, 1, 2),
getLoot(ZSSItems.hookshotUpgrade, UpgradeType.EXTENDER.ordinal(), 1, 1, 1),
getLoot(ZSSItems.hookshotUpgrade, UpgradeType.CLAW.ordinal(), 1, 1, 1),
getLoot(ZSSItems.hookshotUpgrade, UpgradeType.MULTI.ordinal(), 1, 1, 1),
getLoot(ZSSItems.instrument, Instrument.OCARINA_TIME.ordinal(), 1, 1, 1),
getLoot(ZSSItems.keySkeleton, 1, 1, 1),
getLoot(ZSSItems.magicContainer, 1, 1, 1),
getLoot(ZSSItems.magicMirror, 1, 1, 1),
getLoot(ZSSItems.masterOre, 1, 1, 1),
getLoot(ZSSItems.potionBlue, 1, 1, 1),
getLoot(ZSSItems.rocsFeather, 1, 1, 1),
getLoot(ZSSItems.shieldHylian, 1, 1, 2),
getLoot(ZSSItems.slingshot, 1, 1, 2),
getLoot(ZSSItems.whip, IWhipBlock.WhipType.WHIP_SHORT.ordinal(), 1, 1, 2)
});
}
private static void initDefaultLoot() {
setCategoryStats(ChestGenHooks.getInfo(DEFAULT_LOOT), 1, 2, new WeightedRandomChestContent[] {
getLoot(Items.diamond_horse_armor, 1, 1, 1),
getLoot(Items.golden_horse_armor, 1, 1, 1),
getLoot(Items.iron_horse_armor, 1, 1, 2),
getLoot(Items.saddle, 1, 1, 3),
getLoot(ZSSItems.arrowBomb, 2, 5, 3),
getLoot(ZSSItems.bomb, BombType.BOMB_STANDARD.ordinal(), 1, 3, Config.getBombWeight()),
getLoot(ItemBrokenSword.getBrokenSwordFor(ZSSItems.swordOrdon), 1, 1, 1),
getLoot(ZSSItems.swordKokiri, 1, 1, 1)
});
}
private static void initJarDrops() {
setCategoryStats(ChestGenHooks.getInfo(JAR_DROPS), 1, 1, new WeightedRandomChestContent[] {
getLoot(ZSSItems.bomb, BombType.BOMB_STANDARD.ordinal(), 1, 1, 1),
getLoot(ZSSItems.potionRed, 1, 1, 2),
getLoot(ZSSItems.magicJar, 1, 1, 3),
getLoot(ZSSItems.smallHeart, 1, 1, 6),
getLoot(ZSSItems.dekuNut, 1, 1, 4),
getLoot(Items.arrow, 1, 1, 5),
getLoot(Items.emerald, 1, 1, 10)
});
}
private static void initLavaLoot() {
setCategoryStats(ChestGenHooks.getInfo(LAVA_LOOT), 1, 2, new WeightedRandomChestContent[] {
getLoot(Items.nether_wart, 1, 2, 1),
getLoot(Items.potionitem, LibPotionID.FIRERESIST.id, 1, 1, 2),
getLoot(Items.fire_charge, 1, 2, 3),
getLoot(ZSSItems.arrowBombFire, 2, 5, 3),
getLoot(ZSSItems.bomb, BombType.BOMB_FIRE.ordinal(), 1, 2, Config.getBombWeight() * 2),
getLoot(ZSSItems.tunicGoronHelm, 1, 1, 1),
getLoot(ZSSItems.tunicGoronChest, 1, 1, 1),
getLoot(ZSSItems.tunicGoronLegs, 1, 1, 1)
});
}
private static void initLockedLoot() {
setCategoryStats(ChestGenHooks.getInfo(LOCKED_LOOT), 1, 3, new WeightedRandomChestContent[] {
getLoot(ZSSItems.arrowFire, 2, 5, Config.getLockedLootWeight()),
getLoot(ZSSItems.arrowIce, 2, 5, Config.getLockedLootWeight()),
getLoot(ZSSItems.arrowLight, 1, 3, 1),
getLoot(Items.golden_apple, 1, 2, Math.max(Config.getLockedLootWeight() / 3, 1)),
getLoot(Items.potionitem, LibPotionID.HEALING_II.id, 1, 1, Math.max(Config.getLockedLootWeight() / 2, 2)),
getLoot(Items.potionitem, LibPotionID.HEALING_SPLASH.id, 1, 1, Math.max(Config.getLockedLootWeight() / 2, 2)),
getLoot(ZSSItems.bombBag, 1, 1, Config.getBombBagWeight()),
getLoot(ZSSItems.magicMirror, 1, 1, Config.getLockedLootWeight()),
getLoot(ZSSItems.potionBlue, 1, 1, 1),
getLoot(ZSSItems.swordOrdon, 1, 1, Config.getLockedLootWeight()),
getLoot(ZSSItems.tunicHeroBoots, 1, 1, 1),
getLoot(ZSSItems.tunicHeroLegs, 1, 1, 1),
getLoot(ZSSItems.tunicHeroChest, 1, 1, 1),
getLoot(ZSSItems.tunicHeroHelm, 1, 1, 1)
});
}
private static void initMountainLoot() {
setCategoryStats(ChestGenHooks.getInfo(MOUNTAIN_LOOT), 1, 2, new WeightedRandomChestContent[] {
getLoot(Items.potionitem, LibPotionID.STRENGTH_II.id, 1, 1, 1),
getLoot(Items.potionitem, LibPotionID.STRENGTH.id, 1, 1, 3),
getLoot(Items.diamond, 1, 3, 3),
getLoot(ZSSItems.arrowBomb, 2, 5, 3),
getLoot(ZSSItems.bomb, BombType.BOMB_STANDARD.ordinal(), 1, 2, Config.getBombWeight() * 2),
getLoot(ZSSItems.rocsFeather, 1, 1, 1),
getLoot(ItemBrokenSword.getBrokenSwordFor(ZSSItems.swordOrdon), 1, 1, 1)
});
}
private static void initNetherLoot() {
setCategoryStats(ChestGenHooks.getInfo(NETHER_LOOT), 1, 2, new WeightedRandomChestContent[] {
getLoot(Items.ghast_tear, 1, 2, 1),
getLoot(Items.nether_wart, 1, 2, 1),
getLoot(Items.potionitem, LibPotionID.FIRERESIST.id, 1, 1, 2),
getLoot(Items.blaze_rod, 1, 3, 2),
getLoot(Items.fire_charge, 1, 3, 3),
getLoot(Items.magma_cream, 1, 3, 3),
getLoot(ZSSItems.arrowBombFire, 2, 5, 3),
getLoot(ZSSItems.bomb, BombType.BOMB_FIRE.ordinal(), 1, 2, Config.getBombWeight() * 2)
});
}
private static void initOceanLoot() {
setCategoryStats(ChestGenHooks.getInfo(OCEAN_LOOT), 1, 2, new WeightedRandomChestContent[] {
getLoot(Items.fishing_rod, 1, 1, 1),
getLoot(Items.fish, 1, 2, 3),
getLoot(Items.potionitem, LibPotionID.WATER_BREATHING.id, 1, 1, 2),
getLoot(ZSSItems.arrowBombWater, 2, 5, 3),
getLoot(ZSSItems.bomb, BombType.BOMB_WATER.ordinal(), 1, 2, Config.getBombWeight() * 2),
getLoot(ZSSItems.tunicZoraHelm, 1, 1, 1),
getLoot(ZSSItems.tunicZoraChest, 1, 1, 1),
getLoot(ZSSItems.tunicZoraLegs, 1, 1, 1),
getLoot(ZSSItems.tunicZoraBoots, 1, 1, 1)
});
}
private static void initSkillOrbLoot() {
skillOrbLootList = new ArrayList<WeightedRandomChestContent>(SkillBase.getNumSkills());
for (SkillBase skill : SkillBase.getSkills()) {
if (Config.isLootableSkill(skill)) {
skillOrbLootList.add(getLoot(ZSSItems.skillOrb, skill.getId(), 1, 1, Config.getLockedLootWeight()));
}
}
}
}