From ba3c7f590a0fa795c3786f02a6e4830a1b69049a Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 25 Mar 2024 14:00:12 -0400 Subject: [PATCH] v2.4.0: implemented exotic crystals and mossy clump --- .../assets/messages/items/items.properties | 13 +- core/src/main/assets/sprites/items.png | Bin 22497 -> 22665 bytes .../actors/mobs/Mob.java | 13 ++ .../items/Generator.java | 31 ++++- .../items/rings/RingOfWealth.java | 19 ++- .../items/trinkets/ExoticCrystals.java | 55 +++++++++ .../items/trinkets/MossyClump.java | 116 ++++++++++++++++++ .../shatteredpixeldungeon/levels/Level.java | 7 ++ .../levels/painters/RegularPainter.java | 32 +++-- .../rooms/secret/SecretLaboratoryRoom.java | 9 ++ .../rooms/secret/SecretLibraryRoom.java | 9 ++ .../levels/rooms/special/CrystalPathRoom.java | 41 +++++-- .../sprites/ItemSpriteSheet.java | 10 +- 13 files changed, 318 insertions(+), 37 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/ExoticCrystals.java create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/MossyClump.java diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index 4b76397f6..6fcdeaa4f 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -1291,17 +1291,20 @@ items.stones.stoneofshock.desc=This runestone unleashes a blast of electrical en ###trinkets -items.trinkets.exoticcrystal.name=exotic crystal -items.trinkets.exoticcrystal.desc=...\n\nAt its current level it will replace %d%% of potion or scroll drops with their exotic equivalents. This trinket does not affect potions of strength or scrolls of upgrade. +items.trinkets.exoticcrystals.name=exotic crystals +items.trinkets.exoticcrystals.desc=These small pink crystals have the same shape as crystals of alchemical energy. While they can't be used for energy directly, they seem to be somehow influencing the potions and scrolls you find.\n\nAt its current level this trinket will replace %d%% of potion or scroll drops with their exotic equivalents. This does not affect potions of strength, scrolls of upgrade, or items that are generated to help solve hazard rooms. + +items.trinkets.mossyclump.name=mossy clump +items.trinkets.mossyclump.desc=This clump of wet moss seems to hold onto its moisture no matter how hard you squeeze it. It seems to be magically tied to the dungeon itself, making grass and water more likely to appear.\n\nAt its current level this trinket will make %d%% of regular floors become filled with either water or grass instead. items.trinkets.parchmentscrap.name=parchment scrap -items.trinkets.parchmentscrap.desc=This little scrap of parchment looks like it came from a scroll. It has regained some of its magic, and it seems to be influencing weapons and armor found in the dungeon.\n\nAt its current level it will make enchantments/glyphs _%dx_ as common, and curses on weapons and armor _%sx_ as common. Curses on wands, rings, or artifacts are not affected. +items.trinkets.parchmentscrap.desc=This little scrap of parchment looks like it came from a scroll. It has retained some of its magic, and it seems to be influencing weapons and armor found in the dungeon.\n\nAt its current level this trinket will make enchantments and glyphs _%dx_ as common, and curses on weapons and armor _%sx_ as common. Curses on wands, rings, or artifacts are not affected. items.trinkets.petrifiedseed.name=petrified seed -items.trinkets.petrifiedseed.desc=This seed has been fossilised, either by slow geological processes or by magic. The seed seems to be magically influencing the flora of the dungeon, occasionally replacing plant seeds with runestones.\n\nAt its current level it will cause trampled grass to drop runestones instead of seeds _%1$d%%_ of the time, and will also cause high grass to drop items _%2$d%%_ more often. +items.trinkets.petrifiedseed.desc=This seed has been fossilised, either by slow geological processes or by magic. The seed seems to be magically influencing the flora of the dungeon, occasionally replacing plant seeds with runestones.\n\nAt its current level this trinket will cause trampled grass to drop runestones instead of seeds _%1$d%%_ of the time, and will also cause high grass to drop items _%2$d%%_ more often. items.trinkets.ratskull.name=rat skull -items.trinkets.ratskull.desc=This macabre trinket isn't much larger than the skull of a normal rat, which is somehow a rarity down in this dungeon. The skull's magical influence seems to attract the more rare denizens of the dungeon, making them appear far more often.\n\nAt its current level it will make rare exotic enemies _%dx_ as likely to appear. The skull is only half as effective at attracting crystal mimics and armored statues, however. +items.trinkets.ratskull.desc=This macabre trinket isn't much larger than the skull of a normal rat, which is somehow a rarity down in this dungeon. The skull's magical influence seems to attract the more rare denizens of the dungeon, making them appear far more often.\n\nAt its current level this trinket will make rare exotic enemies _%dx_ as likely to appear. The skull is only half as effective at attracting crystal mimics and armored statues, however. items.trinkets.trinketcatalyst.name=trinket catalyst items.trinkets.trinketcatalyst.window_text=The water begins to glow as you use the catalyst. There are a few nearby items you could imbue with magical energy. diff --git a/core/src/main/assets/sprites/items.png b/core/src/main/assets/sprites/items.png index ecf54021649b0fae9bd7151cc4ccdb4edcd68e83..b96fed0fdcc76595591e104a0c4e4b44b216949b 100644 GIT binary patch literal 22665 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 literal 22497 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

Gio4#?9^RD0p4{*xeRedw_aue@>!0HO4f?0 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 I)Si0jUsq&($p8QV 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 145c5fa58..544674d35 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 @@ -61,9 +61,12 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.MasterThievesArmband; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.ExoticPotion; import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ExoticScroll; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfAggression; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ExoticCrystals; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Lucky; @@ -922,6 +925,16 @@ public abstract class Mob extends Char { } else if (loot instanceof Class) { + if (ExoticPotion.regToExo.containsKey(loot)){ + if (Random.Float() < ExoticCrystals.consumableExoticChance()){ + return Generator.random(ExoticPotion.regToExo.get(loot)); + } + } else if (ExoticScroll.regToExo.containsKey(loot)){ + if (Random.Float() < ExoticCrystals.consumableExoticChance()){ + return Generator.random(ExoticScroll.regToExo.get(loot)); + } + } + item = Generator.random( (Class)loot ); } else { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java index d3c75aaea..e36422a74 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java @@ -61,6 +61,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfParalyticG import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfPurity; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfToxicGas; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.ExoticPotion; import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfAccuracy; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfArcana; @@ -87,6 +88,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportat import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTerror; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ExoticScroll; import com.shatteredpixel.shatteredpixeldungeon.items.stones.Runestone; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfAggression; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfAugmentation; @@ -100,6 +102,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFear; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFlock; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfShock; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ExoticCrystals; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MossyClump; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ParchmentScrap; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.PetrifiedSeed; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.RatSkull; @@ -520,9 +524,11 @@ public class Generator { TRINKET.classes = new Class[]{ RatSkull.class, ParchmentScrap.class, - PetrifiedSeed.class + PetrifiedSeed.class, + ExoticCrystals.class, + MossyClump.class }; - TRINKET.defaultProbs = new float[]{ 1, 1, 1 }; + TRINKET.defaultProbs = new float[]{ 1, 1, 1, 1, 1 }; TRINKET.probs = TRINKET.defaultProbs.clone(); for (Category cat : Category.values()){ @@ -582,11 +588,15 @@ public class Generator { //reverts changes to drop chances generates by this item //equivalent of shuffling the card back into the deck, does not preserve order! public static void undoDrop(Item item){ + undoDrop(item.getClass()); + } + + public static void undoDrop(Class cls){ for (Category cat : Category.values()){ - if (item.getClass().isAssignableFrom(cat.superClass)){ + if (cls.isAssignableFrom(cat.superClass)){ if (cat.defaultProbs == null) continue; for (int i = 0; i < cat.classes.length; i++){ - if (item.getClass() == cat.classes[i]){ + if (cls == cat.classes[i]){ cat.probs[i]++; } } @@ -641,13 +651,24 @@ public class Generator { i = Random.chances(cat.probs); } if (cat.defaultProbs != null) cat.probs[i]--; + Class itemCls = cat.classes[i]; if (cat.defaultProbs != null && cat.seed != null){ Random.popGenerator(); cat.dropped++; } - return ((Item) Reflection.newInstance(cat.classes[i])).random(); + if (ExoticPotion.regToExo.containsKey(itemCls)){ + if (Random.Float() < ExoticCrystals.consumableExoticChance()){ + itemCls = ExoticPotion.regToExo.get(itemCls); + } + } else if (ExoticScroll.regToExo.containsKey(itemCls)){ + if (Random.Float() < ExoticCrystals.consumableExoticChance()){ + itemCls = ExoticScroll.regToExo.get(itemCls); + } + } + + return ((Item) Reflection.newInstance(itemCls)).random(); } } 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 eb3c6eabc..d22b42f0e 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 @@ -34,10 +34,13 @@ import com.shatteredpixel.shatteredpixeldungeon.items.bombs.Bomb; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfExperience; import com.shatteredpixel.shatteredpixeldungeon.items.potions.brews.UnstableBrew; import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.ExoticPotion; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.PotionOfDivineInspiration; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ExoticScroll; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfMetamorphosis; import com.shatteredpixel.shatteredpixeldungeon.items.spells.UnstableSpell; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ExoticCrystals; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; @@ -230,10 +233,18 @@ public class RingOfWealth extends Ring { return i.quantity(i.quantity()*2); case 1: i = Generator.randomUsingDefaults(Generator.Category.POTION); - return Reflection.newInstance(ExoticPotion.regToExo.get(i.getClass())); + if (!(i instanceof ExoticPotion)) { + return Reflection.newInstance(ExoticPotion.regToExo.get(i.getClass())); + } else { + return Reflection.newInstance(i.getClass()); + } case 2: i = Generator.randomUsingDefaults(Generator.Category.SCROLL); - return Reflection.newInstance(ExoticScroll.regToExo.get(i.getClass())); + if (!(i instanceof ExoticScroll)){ + return Reflection.newInstance(ExoticScroll.regToExo.get(i.getClass())); + } else { + return Reflection.newInstance(i.getClass()); + } case 3: return Random.Int(2) == 0 ? new UnstableBrew() : new UnstableSpell(); case 4: @@ -255,9 +266,9 @@ public class RingOfWealth extends Ring { case 1: return new StoneOfEnchantment(); case 2: - return new PotionOfExperience(); + return Random.Float() < ExoticCrystals.consumableExoticChance() ? new PotionOfDivineInspiration() : new PotionOfExperience(); case 3: - return new ScrollOfTransmutation(); + return Random.Float() < ExoticCrystals.consumableExoticChance() ? new ScrollOfMetamorphosis() : new ScrollOfTransmutation(); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/ExoticCrystals.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/ExoticCrystals.java new file mode 100644 index 000000000..e49a7e0dd --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/ExoticCrystals.java @@ -0,0 +1,55 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2024 Evan Debenham + * + * This program is free software: 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 + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.trinkets; + +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; + +public class ExoticCrystals extends Trinket { + + { + image = ItemSpriteSheet.EXOTIC_CRYSTALS; + } + + @Override + protected int upgradeEnergyCost() { + return 1 + level(); //TODO + } + + @Override + public String desc() { + return Messages.get(this, "desc", (int)(100*consumableExoticChance(buffedLvl()))); + } + + public static float consumableExoticChance(){ + return consumableExoticChance(trinketLevel(ExoticCrystals.class)); + } + + public static float consumableExoticChance( int level ){ + if (level == -1){ + return 0f; + } else { + return 0.1f + 0.1f*level; + } + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/MossyClump.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/MossyClump.java new file mode 100644 index 000000000..566d50958 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/MossyClump.java @@ -0,0 +1,116 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2024 Evan Debenham + * + * This program is free software: 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 + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.trinkets; + +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.watabou.utils.Bundle; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class MossyClump extends Trinket { + + { + image = ItemSpriteSheet.MOSSY_CLUMP; + } + + @Override + protected int upgradeEnergyCost() { + return 1 + level(); //TODO + } + + @Override + public String desc() { + return Messages.get(this, "desc", (int)(100*overrideNormalLevelChance(buffedLvl()))); + } + + public static float overrideNormalLevelChance(){ + return overrideNormalLevelChance(trinketLevel(MossyClump.class)); + } + + public static float overrideNormalLevelChance( int level ){ + if (level == -1){ + return 0f; + } else { + return 0.25f + 0.25f*level; + } + } + + //true for grass, false for water + //ensures a little consistency of RNG + private ArrayList levelFeels = new ArrayList<>(); + private int shuffles = 0; + + public static Level.Feeling getNextFeeling(){ + MossyClump clump = Dungeon.hero.belongings.getItem(MossyClump.class); + if (clump == null) { + return Level.Feeling.NONE; + } + if (clump.levelFeels.isEmpty()){ + Random.pushGenerator(Dungeon.seed+1); + clump.levelFeels.add(true); + clump.levelFeels.add(true); + clump.levelFeels.add(true); + clump.levelFeels.add(false); + clump.levelFeels.add(false); + clump.levelFeels.add(false); + for (int i = 0; i <= clump.shuffles; i++) { + Random.shuffle(clump.levelFeels); + } + clump.shuffles++; + Random.popGenerator(); + } + + return clump.levelFeels.remove(0) ? Level.Feeling.GRASS : Level.Feeling.WATER; + } + + private static final String FEELS = "feels"; + private static final String SHUFFLES = "shuffles"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + if (!levelFeels.isEmpty()){ + boolean[] storeFeels = new boolean[levelFeels.size()]; + for (int i = 0; i < storeFeels.length; i++){ + storeFeels[i] = levelFeels.get(i); + } + bundle.put(FEELS, storeFeels); + } + bundle.put( SHUFFLES, shuffles ); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + levelFeels.clear(); + if (bundle.contains(FEELS)){ + for (boolean b : bundle.getBooleanArray(FEELS)){ + levelFeels.add(b); + } + } + shuffles = bundle.getInt( SHUFFLES ); + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index 1bafbcc10..cde55d31d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -67,6 +67,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MossyClump; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrinketCatalyst; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding; @@ -259,6 +260,12 @@ public abstract class Level implements Bundlable { case 6: feeling = Feeling.SECRETS; break; + default: + if (Random.Float() < MossyClump.overrideNormalLevelChance()){ + feeling = MossyClump.getNextFeeling(); + } else { + feeling = Feeling.NONE; + } } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java index 0286fc1b3..f876b18bc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java @@ -131,20 +131,26 @@ public abstract class RegularPainter extends Painter { } paintDoors( level, rooms ); + + //use a separate RNG here so that extra painting variance doesn't affect the rest of levelgen + //e.g. this minimizes mossy clump's effect on levelgen + Random.pushGenerator(Random.Long()); + + if (waterFill > 0f) { + paintWater( level, rooms ); + } + + if (grassFill > 0f){ + paintGrass( level, rooms ); + } + + if (nTraps > 0){ + paintTraps( level, rooms ); + } - if (waterFill > 0f) { - paintWater( level, rooms ); - } - - if (grassFill > 0f){ - paintGrass( level, rooms ); - } - - if (nTraps > 0){ - paintTraps( level, rooms ); - } - - decorate( level, rooms ); + decorate( level, rooms ); + + Random.popGenerator(); return true; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/secret/SecretLaboratoryRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/secret/SecretLaboratoryRoom.java index 6495681de..c95b37b9f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/secret/SecretLaboratoryRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/secret/SecretLaboratoryRoom.java @@ -36,6 +36,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfMindVision import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfParalyticGas; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfPurity; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfToxicGas; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.ExoticPotion; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ExoticCrystals; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; @@ -94,6 +96,13 @@ public class SecretLaboratoryRoom extends SecretRoom { Class potionCls = Random.chances(chances); chances.put(potionCls, 0f); + + if (ExoticPotion.regToExo.containsKey(potionCls)){ + if (Random.Float() < ExoticCrystals.consumableExoticChance()){ + potionCls = ExoticPotion.regToExo.get(potionCls); + } + } + level.drop( Reflection.newInstance(potionCls), pos ); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/secret/SecretLibraryRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/secret/SecretLibraryRoom.java index 7b9a98a44..99ce6eeac 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/secret/SecretLibraryRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/secret/SecretLibraryRoom.java @@ -33,6 +33,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetributio import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTerror; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ExoticScroll; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ExoticCrystals; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; @@ -93,6 +95,13 @@ public class SecretLibraryRoom extends SecretRoom { Class scrollCls = Random.chances(chances); chances.put(scrollCls, 0f); + + if (ExoticScroll.regToExo.containsKey(scrollCls)){ + if (Random.Float() < ExoticCrystals.consumableExoticChance()){ + scrollCls = ExoticScroll.regToExo.get(scrollCls); + } + } + level.drop( Reflection.newInstance(scrollCls), pos ); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/CrystalPathRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/CrystalPathRoom.java index 1e7224244..088f33d3c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/CrystalPathRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/CrystalPathRoom.java @@ -26,7 +26,12 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.keys.CrystalKey; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfExperience; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.ExoticPotion; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.PotionOfDivineInspiration; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ExoticScroll; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfMetamorphosis; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ExoticCrystals; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; @@ -165,9 +170,11 @@ public class CrystalPathRoom extends SpecialRoom { if (Random.Int(2) == 0){ addRewardItem(Generator.Category.POTION, potions, duplicates); - scrolls.add(new ScrollOfTransmutation()); + scrolls.add(Random.Float() < ExoticCrystals.consumableExoticChance() + ? new ScrollOfMetamorphosis() : new ScrollOfTransmutation()); } else { - potions.add(new PotionOfExperience()); + potions.add(Random.Float() < ExoticCrystals.consumableExoticChance() + ? new PotionOfDivineInspiration() : new PotionOfExperience()); addRewardItem(Generator.Category.SCROLL, scrolls, duplicates); } addRewardItem(Generator.Category.POTION, potions, duplicates); @@ -177,7 +184,13 @@ public class CrystalPathRoom extends SpecialRoom { //need to undo the changes to spawn chances that the duplicates created for (Item i : duplicates){ - Generator.undoDrop(i); + if (i instanceof ExoticPotion){ + Generator.undoDrop(ExoticPotion.exoToReg.get(i.getClass())); + } else if (i instanceof ExoticScroll){ + Generator.undoDrop(ExoticScroll.exoToReg.get(i.getClass())); + } else { + Generator.undoDrop(i); + } } //rarer potions/scrolls go later in the order @@ -185,9 +198,16 @@ public class CrystalPathRoom extends SpecialRoom { @Override public int compare(Item a, Item b) { int aVal = 0, bVal = 0; + Class aCls = a.getClass(), bCls = b.getClass(); + if (a instanceof ExoticPotion){ + aCls = ExoticPotion.exoToReg.get(aCls); + } + if (b instanceof ExoticPotion){ + bCls = ExoticPotion.exoToReg.get(aCls); + } for (int i = 0; i < Generator.Category.POTION.classes.length; i++){ - if (a.getClass() == Generator.Category.POTION.classes[i]) aVal = (int)Generator.Category.POTION.defaultProbsTotal[i]; - if (b.getClass() == Generator.Category.POTION.classes[i]) bVal = (int)Generator.Category.POTION.defaultProbsTotal[i]; + if (aCls == Generator.Category.POTION.classes[i]) aVal = (int)Generator.Category.POTION.defaultProbsTotal[i]; + if (bCls == Generator.Category.POTION.classes[i]) bVal = (int)Generator.Category.POTION.defaultProbsTotal[i]; } return bVal - aVal; } @@ -196,9 +216,16 @@ public class CrystalPathRoom extends SpecialRoom { @Override public int compare(Item a, Item b) { int aVal = 0, bVal = 0; + Class aCls = a.getClass(), bCls = b.getClass(); + if (a instanceof ExoticScroll){ + aCls = ExoticScroll.exoToReg.get(aCls); + } + if (b instanceof ExoticScroll){ + bCls = ExoticScroll.exoToReg.get(aCls); + } for (int i = 0; i < Generator.Category.SCROLL.classes.length; i++){ - if (a.getClass() == Generator.Category.SCROLL.classes[i]) aVal = (int)Generator.Category.SCROLL.defaultProbsTotal[i]; - if (b.getClass() == Generator.Category.SCROLL.classes[i]) bVal = (int)Generator.Category.SCROLL.defaultProbsTotal[i]; + if (aCls == Generator.Category.SCROLL.classes[i]) aVal = (int)Generator.Category.SCROLL.defaultProbsTotal[i]; + if (bCls == Generator.Category.SCROLL.classes[i]) bVal = (int)Generator.Category.SCROLL.defaultProbsTotal[i]; } return bVal - aVal; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java index 26bcd2330..db1aaebb6 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java @@ -472,10 +472,14 @@ public class ItemSpriteSheet { public static final int RAT_SKULL = TRINKETS+0; public static final int PARCHMENT_SCRAP = TRINKETS+1; public static final int PETRIFIED_SEED = TRINKETS+2; + public static final int EXOTIC_CRYSTALS = TRINKETS+3; + public static final int MOSSY_CLUMP = TRINKETS+4; static{ - assignItemRect(RAT_SKULL, 16, 11); - assignItemRect(PARCHMENT_SCRAP, 10, 14); - assignItemRect(PETRIFIED_SEED, 10, 10); + assignItemRect(RAT_SKULL, 16, 11); + assignItemRect(PARCHMENT_SCRAP, 10, 14); + assignItemRect(PETRIFIED_SEED, 10, 10); + assignItemRect(EXOTIC_CRYSTALS, 11, 11); + assignItemRect(MOSSY_CLUMP, 12, 11); } private static final int SCROLLS = xy(1, 19); //16 slots