2
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
12 KiB
Java

package com.zivilon.cinder_loe.droptables;
import com.zivilon.cinder_loe.util.ILootableEntity;
import com.zivilon.cinder_loe.util.Utilities;
import com.zivilon.cinder_loe.CinderLoE;
import net.minecraft.nbt.*;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.registry.FMLControlledNamespacedRegistry;
import lotr.common.entity.npc.LOTREntityNPC;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class DropTable {
public static Random random = new Random();
public List<DropInstance> drop_list;
public DropTable() {
drop_list = new ArrayList<DropInstance>();
}
public static void drop_items(LOTREntityNPC entity, DropContext[] context_flags, int looting_level) {
List<ItemStack> drops = generate_drops(entity, context_flags, looting_level);
if (drops == null || drops.size() < 1) return;
for (ItemStack drop : drops) {
entity.npcDropItem(drop, 0.0F, false, false);
}
}
public static List<ItemStack> generate_drops(LOTREntityNPC entity, DropContext[] context_flags, int looting_level) {
DropTable table = ((ILootableEntity)entity).get_drop_table();
if (table == null) {
return null;
}
if (context_flags == null) {
context_flags = new DropContext[0];
}
List<ItemStack> results = new ArrayList<>();
for (DropInstance drop : table.drop_list) {
ItemStack stack = get_drop(drop, looting_level, context_flags);
if (stack != null) {
results.add(stack);
}
}
return results;
}
public static ItemStack get_drop(DropInstance drop, int looting_level, DropContext[] context) {
if (!(Utilities.array_contains_array(context, drop.conditions))) return null;
if (drop instanceof SingleItemDrop) {
return get_single_drop((SingleItemDrop)drop, looting_level);
}
if (drop instanceof ItemGroup) {
return get_group_drop((ItemGroup)drop, looting_level);
}
return null;
}
public static ItemStack get_single_drop(SingleItemDrop drop, int looting_level) {
float chance = drop.drop_chance;
if (drop.looting_affects_chance)
chance = 1.0F - (float)Math.pow(1.0F - chance, 1.0F + 0.1F * looting_level);
if (chance < random.nextFloat()) return null;
int range = drop.max_amount - drop.min_amount + 1;
if (drop.looting_affects_quantity && looting_level > 0)
range = (int)Math.ceil(range * (1.25F * looting_level));
int count = random.nextInt(range) + drop.min_amount;
ItemStack stack = new ItemStack(drop.item, count);
if (drop.nbt != null)
stack.setTagCompound((NBTTagCompound)drop.nbt.copy());
return stack;
}
public static ItemStack get_group_drop(ItemGroup drop, int looting_level) {
float chance = drop.drop_chance;
if (drop.looting_affects_chance)
chance = 1.0F - (float)Math.pow(1.0F - chance, 1.0F + 0.1F * looting_level);
if (chance < random.nextFloat()) return null;
int total_weight = drop.entries.stream().mapToInt(e -> e.weight).sum();
int pick = random.nextInt(total_weight);
for (ItemGroupEntry entry : drop.entries) {
if (pick < entry.weight) {
int range = entry.max_amount - entry.min_amount + 1;
if (entry.looting_affects_quantity && looting_level > 0)
range = (int)Math.ceil(range * (1.25F * looting_level));
int count = random.nextInt(range) + entry.min_amount;
ItemStack stack = new ItemStack(entry.item, count);
if (entry.nbt != null)
stack.setTagCompound((NBTTagCompound)entry.nbt.copy());
return stack;
}
pick -= entry.weight;
}
return null;
}
public static NBTTagCompound serialize_to_nbt(DropTable table) {
NBTTagCompound nbt = new NBTTagCompound();
NBTTagList drop_list = new NBTTagList();
for (DropInstance drop : table.drop_list) {
NBTTagCompound drop_tag = new NBTTagCompound();
drop_tag.setString("type", drop instanceof ItemGroup ? "group" : "single");
drop_tag.setFloat("drop_chance", drop.drop_chance);
drop_tag.setInteger("min_amount", drop.min_amount);
drop_tag.setInteger("max_amount", drop.max_amount);
drop_tag.setBoolean("looting_affects_chance", drop.looting_affects_chance);
NBTTagList condition_list = new NBTTagList();
if (drop instanceof SingleItemDrop) {
SingleItemDrop single = (SingleItemDrop)drop;
Item drop_item = single.item;
drop_tag.setBoolean("looting_affects_quantity", single.looting_affects_quantity);
drop_tag.setInteger("id", ((FMLControlledNamespacedRegistry)Item.itemRegistry).getId(drop_item));
if (single.nbt != null)
drop_tag.setTag("nbt", single.nbt);
}
if (drop instanceof ItemGroup) {
ItemGroup group = (ItemGroup) drop;
NBTTagList entries = new NBTTagList();
for (ItemGroupEntry entry : group.entries) {
NBTTagCompound entry_tag = new NBTTagCompound();
entry_tag.setInteger("id", Item.getIdFromItem(entry.item));
entry_tag.setInteger("weight", entry.weight);
entry_tag.setInteger("min", entry.min_amount);
entry_tag.setInteger("max", entry.max_amount);
entry_tag.setBoolean("looting_quantity", entry.looting_affects_quantity);
if (entry.nbt != null) {
entry_tag.setTag("nbt", entry.nbt.copy());
}
entries.appendTag(entry_tag);
}
drop_tag.setTag("entries", entries);
}
for (DropContext condition : drop.conditions) {
condition_list.appendTag(new NBTTagString(condition.name()));
}
drop_tag.setTag("conditions", condition_list);
drop_list.appendTag(drop_tag);
nbt.setTag("Drops", drop_list);
}
return nbt;
}
public static DropTable deserialize_from_nbt(NBTTagCompound tag) {
DropTable table = new DropTable();
if (!tag.hasKey("Drops")) return table;
NBTTagList drop_list = tag.getTagList("Drops", 10);
for (int i = 0; i < drop_list.tagCount(); i++) {
NBTTagCompound drop_tag = drop_list.getCompoundTagAt(i);
String type = drop_tag.getString("type");
float drop_chance = drop_tag.getFloat("drop_chance");
int min = drop_tag.getInteger("min_amount");
int max = drop_tag.getInteger("max_amount");
boolean looting_chance = drop_tag.getBoolean("looting_affects_chance");
// Read conditions
DropContext[] conditions;
if (drop_tag.hasKey("conditions")) {
NBTTagList cond_list = drop_tag.getTagList("conditions", 8);
conditions = new DropContext[cond_list.tagCount()];
for (int j = 0; j < cond_list.tagCount(); j++) {
String ctx = cond_list.getStringTagAt(j);
conditions[j] = DropContext.valueOf(ctx);
}
} else {
conditions = new DropContext[0];
}
// Construct drop
if (type.equals("single")) {
Item item = Item.getItemById(drop_tag.getInteger("id"));
boolean looting_quantity = drop_tag.hasKey("looting_affects_quantity") && drop_tag.getBoolean("looting_affects_quantity");
NBTTagCompound nbt = drop_tag.hasKey("nbt") ? drop_tag.getCompoundTag("nbt") : null;
SingleItemDrop single = new SingleItemDrop(item, nbt, drop_chance, min, max, looting_quantity, looting_chance, conditions);
if (single != null) table.drop_list.add(single);
if (single == null) System.out.println("[DropTable_deserializer] WARNING: Single drop was null!");
} else if (type.equals("group")) {
List<ItemGroupEntry> entries = new ArrayList<>();
if (drop_tag.hasKey("entries")) {
NBTTagList entry_list = drop_tag.getTagList("entries", 10); // 10 = compound
for (int j = 0; j < entry_list.tagCount(); j++) {
NBTTagCompound entry_tag = entry_list.getCompoundTagAt(j);
Item item = Item.getItemById(entry_tag.getInteger("id"));
int weight = entry_tag.getInteger("weight");
int minAmt = entry_tag.getInteger("min");
int maxAmt = entry_tag.getInteger("max");
boolean lootQty = entry_tag.getBoolean("looting_quantity");
NBTTagCompound nbt = entry_tag.hasKey("nbt") ? entry_tag.getCompoundTag("nbt") : null;
entries.add(new ItemGroupEntry(item, nbt, weight, minAmt, maxAmt, lootQty));
}
}
ItemGroup group = new ItemGroup(drop_chance, min, max, looting_chance, conditions, entries.toArray(new ItemGroupEntry[0]));
if (group != null) table.drop_list.add(group);
if (group == null) System.out.println("[DropTable_deserializer] WARNING: Group drop was null!");
}
}
return table;
}
public static class DropInstance {
public float drop_chance;
public int min_amount;
public int max_amount;
public boolean looting_affects_chance;
public DropContext[] conditions;
public DropInstance(float drop_chance, int min_amount, int max_amount, boolean looting_chance, DropContext[] conditions) {
this.drop_chance = drop_chance;
this.min_amount = min_amount;
this.max_amount = max_amount;
this.looting_affects_chance = looting_chance;
this.conditions = conditions;
}
}
public static class SingleItemDrop extends DropInstance {
public Item item;
public NBTTagCompound nbt;
boolean looting_affects_quantity;
public SingleItemDrop(Item item, NBTTagCompound nbt, float chance, int min, int max, boolean looting_quantity, boolean looting_chance, DropContext[] conditions) {
super(chance, min, max, looting_chance, conditions);
this.item = item;
this.nbt = nbt;
this.looting_affects_quantity = looting_quantity;
}
public SingleItemDrop(Item item, NBTTagCompound nbt, float chance, DropContext[] conditions) {
super(chance, 1, 1, false, conditions);
this.item = item;
this.nbt = nbt;
this.looting_affects_quantity = false;
}
}
public static class ItemGroup extends DropInstance {
public List<ItemGroupEntry> entries;
public ItemGroup(float chance, int min, int max, boolean looting_chance, DropContext[] conditions, ItemGroupEntry... drops) {
super(chance, min, max, looting_chance, conditions);
this.entries = Arrays.asList(drops);
}
}
public static class ItemGroupEntry {
public Item item;
public int min_amount;
public int max_amount;
public NBTTagCompound nbt;
public int weight;
public boolean looting_affects_quantity;
public ItemGroupEntry(Item item, NBTTagCompound nbt, int weight, int min_amount, int max_amount, boolean looting_quantity) {
this.item = item;
this.nbt = nbt;
this.weight = weight;
this.min_amount = min_amount;
this.max_amount = max_amount;
this.looting_affects_quantity = looting_quantity;
}
public ItemGroupEntry(Item item, NBTTagCompound nbt, int weight) {
this.item = item;
this.nbt = nbt;
this.weight = weight;
this.min_amount = 1;
this.max_amount = 1;
this.looting_affects_quantity = false;
}
}
}