diff --git a/assets/icons.png b/assets/icons.png index 3ec50e766..b0051ddf9 100644 Binary files a/assets/icons.png and b/assets/icons.png differ diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java b/src/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java index d5689c804..8ba7fc5c3 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java @@ -76,13 +76,12 @@ import java.util.HashSet; public class Dungeon { - - public static boolean dewVial; // true if the dew vial can be spawned public static int transmutation; // depth number for a well of transmutation //enum of items which have limited spawns, records how many have spawned - //could all be their own separate ints, but this allows iterating, much nicer for bundling/initializing. + //could all be their own separate numbers, but this allows iterating, much nicer for bundling/initializing. public static enum limitedDrops{ + //limited world drops strengthPotions, upgradeScrolls, arcaneStyli, @@ -93,12 +92,28 @@ public class Dungeon { warlockHP, scorpioHP, cookingHP, - + //blandfruit, which can technically be an unlimited health potion source blandfruitSeed, - armband; + //doesn't use Generator, so we have to enforce one armband drop here + armband, + + //containers + dewVial, + seedBag, + scrollBag, + potionBag, + wandBag; public int count = 0; + + //for items which can only be dropped once, should directly access count otherwise. + public boolean dropped(){ + return count != 0; + } + public void drop(){ + count = 1; + } } public static int challenges; @@ -146,7 +161,6 @@ public class Dungeon { for (limitedDrops a : limitedDrops.values()) a.count = 0; - dewVial = true; transmutation = Random.IntRange( 6, 14 ); chapters = new HashSet(); @@ -413,7 +427,6 @@ public class Dungeon { quickslot.storePlaceholders( bundle ); - bundle.put( DV, dewVial ); bundle.put( WT, transmutation ); int[] dropValues = new int[limitedDrops.values().length]; @@ -523,7 +536,8 @@ public class Dungeon { if (fullLoad) { - dewVial = bundle.getBoolean( DV ); + //for pre-0.2.4 saves + if (bundle.getBoolean(DV)) limitedDrops.dewVial.drop(); transmutation = bundle.getInt( WT ); //TODO: adjust this when dropping support for pre-0.2.3 saves @@ -579,6 +593,14 @@ public class Dungeon { Statistics.restoreFromBundle( bundle ); Journal.restoreFromBundle( bundle ); Generator.restoreFromBundle( bundle ); + + //logic for pre 0.2.4 bags, remove when no longer supporting those saves. + if (version <= 32){ + int deepest = Statistics.deepestFloor; + if (deepest > 15) limitedDrops.wandBag.count = 1; + if (deepest > 10) limitedDrops.scrollBag.count = 1; + if (deepest > 5) limitedDrops.seedBag.count = 1; + } } public static Level loadLevel( HeroClass cl ) throws IOException { diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java index 70785f85d..c030eaf83 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Thief.java @@ -90,8 +90,8 @@ public class Thief extends Mob { @Override protected Item createLoot(){ - if (Dungeon.limitedDrops.armband.count == 0) { - Dungeon.limitedDrops.armband.count++; + if (!Dungeon.limitedDrops.armband.dropped()) { + Dungeon.limitedDrops.armband.drop(); return super.createLoot(); } else return new Gold(Random.NormalIntRange(100, 250)); diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/PotionBandolier.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/PotionBandolier.java new file mode 100644 index 000000000..86b2dc586 --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/PotionBandolier.java @@ -0,0 +1,35 @@ +package com.shatteredpixel.shatteredpixeldungeon.items.bags; + +import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; + +/** + * Created by debenhame on 05/02/2015. + */ +public class PotionBandolier extends Bag { + + { + name = "potion bandolier"; + image = ItemSpriteSheet.BANDOLIER; + + size = 12; + } + + @Override + public boolean grab( Item item ) { + return item instanceof Potion; + } + + @Override + public int price() { + return 50; + } + + @Override + public String info() { + return + "This thick bandoler fits around your chest like a sash, holding onto your potions for you.\n\n" + + "It is made of warm animal hide, which should protect your potions from the cold."; + } +} diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/ScrollHolder.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/ScrollHolder.java index 9039d8908..239ef374d 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/ScrollHolder.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/ScrollHolder.java @@ -43,7 +43,7 @@ public class ScrollHolder extends Bag { @Override public String info() { return - "You can place any number of scrolls into this tubular container. " + - "It saves room in your backpack and protects scrolls from fire."; + "This tubular container looks like it would hold an astronomer's charts, but your scrolls will fit just as well.\n\n" + + "The holder doesn't look very flammable, so your scrolls should be safe from fire inside it."; } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/WandHolster.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/WandHolster.java index eef19657f..0b5af3981 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/WandHolster.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/bags/WandHolster.java @@ -64,7 +64,7 @@ public class WandHolster extends Bag { @Override public String info() { return - "This slim holder is made of leather of some exotic animal. " + - "It allows to compactly carry up to " + size + " wands."; + "This slim holster is made from some exotic animal, and is designed to compactly carry up to " + size + " wands.\n\n" + + "The size seems a bit excessive, who would ever have that many wands?"; } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/SewerLevel.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/SewerLevel.java index 16bd72946..4b868bdb8 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/SewerLevel.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/SewerLevel.java @@ -104,9 +104,9 @@ public class SewerLevel extends RegularLevel { @Override protected void createItems() { - if (Dungeon.dewVial && Random.Int( 4 - Dungeon.depth ) == 0) { + if (!Dungeon.limitedDrops.dewVial.dropped() && Random.Int( 4 - Dungeon.depth ) == 0) { addItemToSpawn( new DewVial() ); - Dungeon.dewVial = false; + Dungeon.limitedDrops.dewVial.drop(); } Ghost.Quest.spawn( this ); diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/painters/ShopPainter.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/painters/ShopPainter.java index 723f2bbc7..85c9a2226 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/painters/ShopPainter.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/painters/ShopPainter.java @@ -18,6 +18,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.painters; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.ImpShopkeeper; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper; @@ -32,14 +33,19 @@ import com.shatteredpixel.shatteredpixeldungeon.items.armor.MailArmor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.PlateArmor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.ScaleArmor; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass; +import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag; +import com.shatteredpixel.shatteredpixeldungeon.items.bags.PotionBandolier; import com.shatteredpixel.shatteredpixeldungeon.items.bags.ScrollHolder; import com.shatteredpixel.shatteredpixeldungeon.items.bags.SeedPouch; import com.shatteredpixel.shatteredpixeldungeon.items.bags.WandHolster; import com.shatteredpixel.shatteredpixeldungeon.items.food.OverpricedRation; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfIdentify; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMagicMapping; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRemoveCurse; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.BattleAxe; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Glaive; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Longsword; @@ -52,6 +58,7 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.LastShopLevel; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; import com.watabou.utils.Point; import com.watabou.utils.Random; @@ -112,21 +119,18 @@ public class ShopPainter extends Painter { case 6: itemsToSpawn.add( (Random.Int( 2 ) == 0 ? new Quarterstaff() : new Spear()).identify() ); itemsToSpawn.add( new LeatherArmor().identify() ); - itemsToSpawn.add( new SeedPouch() ); itemsToSpawn.add( new Weightstone() ); break; case 11: itemsToSpawn.add( (Random.Int( 2 ) == 0 ? new Sword() : new Mace()).identify() ); itemsToSpawn.add( new MailArmor().identify() ); - itemsToSpawn.add( new ScrollHolder() ); itemsToSpawn.add( new Weightstone() ); break; case 16: itemsToSpawn.add( (Random.Int( 2 ) == 0 ? new Longsword() : new BattleAxe()).identify() ); itemsToSpawn.add( new ScaleArmor().identify() ); - itemsToSpawn.add( new WandHolster() ); itemsToSpawn.add( new Weightstone() ); break; @@ -147,6 +151,9 @@ public class ShopPainter extends Painter { break; } + Bag bag = ChooseBag(Dungeon.hero.belongings); + if (bag != null) itemsToSpawn.add( bag ); + itemsToSpawn.add( new PotionOfHealing() ); for (int i=0; i < 3; i++) { itemsToSpawn.add( Generator.random( Generator.Category.POTION ) ); @@ -193,6 +200,55 @@ public class ShopPainter extends Painter { Collections.shuffle(itemsToSpawn); } + private static Bag ChooseBag(Belongings pack){ + //FIXME: this whole method is pretty messy to accomplish a fairly simple logic goal. Should be a better way. + + //there is a bias towards giving certain bags earlier, seen here + int seeds = 2, scrolls = 1, potions = 1, wands = 0; + + //we specifically only want to look at items in the main bag, none of the sub-bags. + for (Item item : pack.backpack.items){ + if (item instanceof Plant.Seed) + seeds++; + else if (item instanceof Scroll) + scrolls++; + else if (item instanceof Potion) + potions++; + else if (item instanceof Wand) + wands++; + } + //...and the equipped weapon incase it's a wand + if (pack.weapon instanceof Wand) + wands++; + + //kill our counts for bags that have already been dropped. + if (Dungeon.limitedDrops.seedBag.dropped()) + seeds = 0; + if (Dungeon.limitedDrops.scrollBag.dropped()) + scrolls = 0; + if (Dungeon.limitedDrops.potionBag.dropped()) + potions = 0; + if (Dungeon.limitedDrops.wandBag.dropped()) + wands = 0; + + //then pick whichever valid bag has the most items available to put into it. + if (seeds >= scrolls && seeds >= potions && seeds >= wands && !Dungeon.limitedDrops.seedBag.dropped()) { + Dungeon.limitedDrops.seedBag.drop(); + return new SeedPouch(); + } else if (scrolls >= potions && scrolls >= wands && !Dungeon.limitedDrops.scrollBag.dropped()) { + Dungeon.limitedDrops.scrollBag.drop(); + return new ScrollHolder(); + } else if (potions >= wands && !Dungeon.limitedDrops.potionBag.dropped()) { + Dungeon.limitedDrops.potionBag.drop(); + return new PotionBandolier(); + } else if (!Dungeon.limitedDrops.wandBag.dropped()) { + Dungeon.limitedDrops.wandBag.drop(); + return new WandHolster(); + } else + return null; + + } + public static int spaceNeeded(){ if (itemsToSpawn == null) generateItems(); diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java b/src/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java index d4aa233cf..218bc9e16 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java @@ -45,6 +45,7 @@ public enum Icons { BACKPACK, SEED_POUCH, SCROLL_HOLDER, + POTION_BANDOLIER, WAND_HOLSTER, CHECKED, UNCHECKED, @@ -129,6 +130,9 @@ public enum Icons { case WAND_HOLSTER: icon.frame( icon.texture.uvRect( 88, 0, 98, 10 ) ); break; + case POTION_BANDOLIER: + icon.frame( icon.texture.uvRect( 98, 0, 108, 10 ) ); + break; case CHECKED: icon.frame( icon.texture.uvRect( 54, 12, 66, 24 ) ); break; @@ -136,7 +140,7 @@ public enum Icons { icon.frame( icon.texture.uvRect( 66, 12, 78, 24 ) ); break; case EXIT: - icon.frame( icon.texture.uvRect( 98, 0, 114, 16 ) ); + icon.frame( icon.texture.uvRect( 108, 0, 124, 16 ) ); break; case CHALLENGE_OFF: icon.frame( icon.texture.uvRect( 78, 16, 102, 40 ) ); diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java index 920e074c8..0ca880ffc 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java @@ -20,6 +20,7 @@ package com.shatteredpixel.shatteredpixeldungeon.windows; import android.graphics.RectF; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem; @@ -27,6 +28,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Gold; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag; +import com.shatteredpixel.shatteredpixeldungeon.items.bags.PotionBandolier; import com.shatteredpixel.shatteredpixeldungeon.items.bags.ScrollHolder; import com.shatteredpixel.shatteredpixeldungeon.items.bags.SeedPouch; import com.shatteredpixel.shatteredpixeldungeon.items.bags.WandHolster; @@ -67,24 +69,24 @@ public class WndBag extends WndTabbed { SCROLL, EQUIPMENT } - + protected static final int COLS = 4; - + protected static final int SLOT_SIZE = 28; protected static final int SLOT_MARGIN = 1; - protected static final int TAB_WIDTH = 30; + protected static final int TAB_WIDTH = 25; protected static final int TITLE_HEIGHT = 12; @SuppressWarnings("unused") - protected static final int ROWS = + protected static final int ROWS = (Belongings.BACKPACK_SIZE + 4 + 1) / COLS + ((Belongings.BACKPACK_SIZE + 4 + 1) % COLS > 0 ? 1 : 0); - + private Listener listener; private WndBag.Mode mode; private String title; - + protected int count; protected int col; protected int row; @@ -102,7 +104,7 @@ public class WndBag extends WndTabbed { lastMode = mode; lastBag = bag; - + BitmapText txtTitle = PixelScene.createText( title != null ? title : Utils.capitalize( bag.name() ), 9 ); txtTitle.hardlight( TITLE_COLOR ); txtTitle.measure(); @@ -111,17 +113,18 @@ public class WndBag extends WndTabbed { add( txtTitle ); placeItems( bag ); - - resize( - SLOT_SIZE * COLS + SLOT_MARGIN * (COLS - 1), + + resize( + SLOT_SIZE * COLS + SLOT_MARGIN * (COLS - 1), SLOT_SIZE * ROWS + SLOT_MARGIN * (ROWS - 1) + TITLE_HEIGHT ); - + Belongings stuff = Dungeon.hero.belongings; Bag[] bags = { stuff.backpack, stuff.getItem( SeedPouch.class ), stuff.getItem( ScrollHolder.class ), - stuff.getItem( WandHolster.class )}; + stuff.getItem( WandHolster.class ), + stuff.getItem(PotionBandolier.class)}; for (Bag b : bags) { if (b != null) { @@ -163,7 +166,7 @@ public class WndBag extends WndTabbed { placeItem( stuff.armor != null ? stuff.armor : new Placeholder( ItemSpriteSheet.ARMOR ) ); placeItem( stuff.misc1 != null ? stuff.misc1 : new Placeholder( ItemSpriteSheet.RING ) ); placeItem( stuff.misc2 != null ? stuff.misc2 : new Placeholder( ItemSpriteSheet.RING ) ); - + // Unequipped items for (Item item : container.items) { placeItem( item ); @@ -266,6 +269,8 @@ public class WndBag extends WndTabbed { return Icons.get( Icons.SCROLL_HOLDER ); } else if (bag instanceof WandHolster) { return Icons.get( Icons.WAND_HOLSTER ); + } else if (bag instanceof PotionBandolier) { + return Icons.get( Icons.POTION_BANDOLIER ); } else { return Icons.get( Icons.BACKPACK ); }