diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java index 6997a797c..df5534e72 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java @@ -632,10 +632,15 @@ public abstract class Mob extends Char { int rolls = 1; if (properties.contains(Property.BOSS)) rolls = 15; else if (properties.contains(Property.MINIBOSS)) rolls = 5; - ArrayList bonus = RingOfWealth.tryRareDrop(Dungeon.hero, rolls); - if (bonus != null) { + ArrayList bonus = RingOfWealth.tryForBonusDrop(Dungeon.hero, rolls); + if (!bonus.isEmpty()) { for (Item b : bonus) Dungeon.level.drop(b, pos).sprite.drop(); - new Flare(8, 32).color(0xFFFF00, true).show(sprite, 2f); + if (RingOfWealth.latestDropWasRare){ + new Flare(8, 48).color(0xAA00FF, true).show(sprite, 2f); + RingOfWealth.latestDropWasRare = false; + } else { + new Flare(8, 24).color(0xFFFFFF, true).show(sprite, 2f); + } } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java index cabdf30c0..cdf44f906 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java @@ -140,10 +140,15 @@ public class Heap implements Bundlable { if (type != Type.MIMIC) { type = Type.HEAP; - ArrayList bonus = RingOfWealth.tryRareDrop(hero, 1); - if (bonus != null){ + ArrayList bonus = RingOfWealth.tryForBonusDrop(hero, 1); + if (!bonus.isEmpty()) { items.addAll(0, bonus); - new Flare(8, 32).color(0xFFFF00, true).show(sprite, 2f); + if (RingOfWealth.latestDropWasRare){ + new Flare(8, 48).color(0xAA00FF, true).show(sprite, 2f); + RingOfWealth.latestDropWasRare = false; + } else { + new Flare(8, 24).color(0xFFFFFF, true).show(sprite, 2f); + } } sprite.link(); sprite.drop(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfWealth.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfWealth.java index e67dac968..8238c88ef 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfWealth.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfWealth.java @@ -21,13 +21,21 @@ package com.shatteredpixel.shatteredpixeldungeon.items.rings; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Gold; -import com.shatteredpixel.shatteredpixeldungeon.items.Honeypot; import com.shatteredpixel.shatteredpixeldungeon.items.Item; -import com.shatteredpixel.shatteredpixeldungeon.items.bombs.Bomb; +import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.AlchemicalCatalyst; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfExperience; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfEnchantment; +import com.shatteredpixel.shatteredpixeldungeon.items.spells.ArcaneCatalyst; +import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.watabou.utils.Bundle; import com.watabou.utils.Random; import java.text.DecimalFormat; @@ -36,7 +44,10 @@ import java.util.HashSet; public class RingOfWealth extends Ring { - private float triesToDrop = 0; + private float triesToDrop = Float.MIN_VALUE; + private int dropsToRare = Integer.MIN_VALUE; + + public static boolean latestDropWasRare = false; public String statsInfo() { if (isIdentified()){ @@ -45,7 +56,24 @@ public class RingOfWealth extends Ring { return Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(20f)); } } - + + private static final String TRIES_TO_DROP = "tries_to_drop"; + private static final String DROPS_TO_RARE = "drops_to_rare"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(TRIES_TO_DROP, triesToDrop); + bundle.put(DROPS_TO_RARE, dropsToRare); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + triesToDrop = bundle.getFloat(TRIES_TO_DROP); + dropsToRare = bundle.getInt(DROPS_TO_RARE); + } + @Override protected RingBuff buff( ) { return new Wealth(); @@ -55,93 +83,169 @@ public class RingOfWealth extends Ring { return (float)Math.pow(1.2, getBonus(target, Wealth.class)); } - public static ArrayList tryRareDrop(Char target, int tries ){ + public static ArrayList tryForBonusDrop(Char target, int tries ){ if (getBonus(target, Wealth.class) <= 0) return null; HashSet buffs = target.buffs(Wealth.class); - float triesToDrop = -1; + float triesToDrop = Float.MIN_VALUE; + int dropsToRare = Integer.MIN_VALUE; //find the largest count (if they aren't synced yet) for (Wealth w : buffs){ if (w.triesToDrop() > triesToDrop){ triesToDrop = w.triesToDrop(); + dropsToRare = w.dropsToRare(); } } - + //reset (if needed), decrement, and store counts - if (triesToDrop <= 0) triesToDrop += Random.NormalIntRange(15, 60); - triesToDrop -= dropProgression( target, tries ); + if (triesToDrop == Float.MIN_VALUE) { + triesToDrop = Random.NormalIntRange(0, 60); + dropsToRare = Random.NormalIntRange(0, 20); + } + + //now handle reward logic + ArrayList drops = new ArrayList<>(); + + triesToDrop -= dropProgression(target, tries); + while ( triesToDrop <= 0 ){ + if (dropsToRare <= 0){ + drops.add(genRareDrop()); + latestDropWasRare = true; + dropsToRare = Random.NormalIntRange(0, 20); + } else { + drops.add(genStandardDrop()); + dropsToRare--; + } + triesToDrop += Random.NormalIntRange(0, 60); + } + + //store values back into rings for (Wealth w : buffs){ w.triesToDrop(triesToDrop); + w.dropsToRare(dropsToRare); } - //now handle reward logic - if (triesToDrop <= 0){ - return generateRareDrop(); - } else { - return null; - } - + return drops; } - //TODO this is a start, but i'm sure this could be made more interesting... - private static ArrayList generateRareDrop(){ + public static Item genStandardDrop(){ float roll = Random.Float(); - ArrayList items = new ArrayList<>(); - if (roll < 0.6f){ - switch (Random.Int(3)){ - case 0: - items.add(new Gold().random()); - break; - case 1: - items.add(Generator.random(Generator.Category.POTION)); - break; - case 2: - items.add(Generator.random(Generator.Category.SCROLL)); - break; + if (roll < 0.3f){ //30% chance + Item result = new Gold().random(); + result.quantity(Math.round(result.quantity() * Random.NormalFloat(0.33f, 1f))); + return result; + } else if (roll < 0.7f){ //40% chance + return genBasicConsumable(); + } else if (roll < 0.9f){ //20% chance + return genExoticConsumable(); + } else { //10% chance + if (Random.Int(3) != 0){ + Weapon weapon = Generator.randomWeapon(); + weapon.enchant(null); + weapon.cursed = false; + weapon.cursedKnown = true; + weapon.level(0); + return weapon; + } else { + Armor armor = Generator.randomArmor(); + armor.inscribe(null); + armor.cursed = false; + armor.cursedKnown = true; + armor.level(0); + return armor; } - } else if (roll < 0.9f){ - switch (Random.Int(3)){ - case 0: - items.add(Generator.random(Generator.Category.SEED)); - items.add(Generator.random(Generator.Category.SEED)); - items.add(Generator.random(Generator.Category.SEED)); - items.add(Generator.random(Generator.Category.SEED)); - items.add(Generator.random(Generator.Category.SEED)); - break; - case 1: - items.add(Generator.random(Random.Int(2) == 0 ? Generator.Category.POTION : Generator.Category.SCROLL )); - items.add(Generator.random(Random.Int(2) == 0 ? Generator.Category.POTION : Generator.Category.SCROLL )); - items.add(Generator.random(Random.Int(2) == 0 ? Generator.Category.POTION : Generator.Category.SCROLL )); - break; - case 2: - items.add(new Bomb().random()); - items.add(new Honeypot()); - break; - } - } else { - Gold g = new Gold(); - g.random(); - g.quantity(g.quantity()*5); - items.add(g); } - return items; + } + + private static Item genBasicConsumable(){ + float roll = Random.Float(); + if (roll < 0.4f){ //40% chance + return Generator.random(Generator.Category.STONE); + } else if (roll < 0.7f){ //30% chance + return Generator.random(Generator.Category.POTION); + } else { //30% chance + return Generator.random(Generator.Category.SCROLL); + } + } + + private static Item genExoticConsumable(){ + float roll = Random.Float(); + if (roll < 0.3f){ //30% chance + return Generator.random(Generator.Category.POTION); + } else if (roll < 0.6f) { //30% chance + return Generator.random(Generator.Category.SCROLL); + } else { //40% chance + return Random.Int(2) == 0 ? new AlchemicalCatalyst() : new ArcaneCatalyst(); + } + } + + public static Item genRareDrop(){ + float roll = Random.Float(); + if (roll < 0.3f){ //30% chance + Item result = new Gold().random(); + result.quantity(Math.round(result.quantity() * Random.NormalFloat(3f, 6f))); + return result; + } else if (roll < 0.7f){ //40% chance + return genHighValueConsumable(); + } else if (roll < 0.9f){ //20% chance + Item result = Random.Int(2) == 0 ? Generator.random(Generator.Category.ARTIFACT) : Generator.random(Generator.Category.RING); + result.cursed = false; + result.cursedKnown = true; + return result; + } else { //10% chance + if (Random.Int(3) != 0){ + Weapon weapon = Generator.randomWeapon((Dungeon.depth / 5) + 1); + weapon.upgrade(1); + weapon.enchant(Weapon.Enchantment.random()); + weapon.cursed = false; + weapon.cursedKnown = true; + return weapon; + } else { + Armor armor = Generator.randomArmor((Dungeon.depth / 5) + 1); + armor.upgrade(); + armor.inscribe(Armor.Glyph.random()); + armor.cursed = false; + armor.cursedKnown = true; + return armor; + } + } + } + + private static Item genHighValueConsumable(){ + switch( Random.Int(4) ){ //25% chance each + case 0: default: + return new StoneOfEnchantment(); + case 1: + return new ScrollOfEnchantment(); + case 2: + return new PotionOfExperience(); + case 3: + return new ScrollOfTransmutation(); + } } private static float dropProgression( Char target, int tries ){ - return tries * (float)Math.pow(1.2f, getBonus(target, Wealth.class) -1 ); + return tries * (float)Math.pow(1.2f, getBonus(target, Wealth.class) ); } public class Wealth extends RingBuff { - private void triesToDrop( float val){ + private void triesToDrop( float val ){ triesToDrop = val; } private float triesToDrop(){ return triesToDrop; } - + + private void dropsToRare( int val ) { + dropsToRare = val; + } + + private int dropsToRare(){ + return dropsToRare; + } } }