From e53c6b678f9d3c5777f858bd473bb35f44d2e596 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 19 Jan 2015 12:01:04 -0500 Subject: [PATCH] v0.2.3e: added backend support for multiple quickslots (needs testing!) --- .../shatteredpixeldungeon/Dungeon.java | 17 --- .../actors/hero/Belongings.java | 8 +- .../actors/hero/Hero.java | 2 +- .../actors/hero/HeroClass.java | 16 +-- .../actors/hero/QuickSlot.java | 107 ++++++++++++++++++ .../shatteredpixeldungeon/items/Item.java | 26 +++-- .../shatteredpixeldungeon/ui/QuickSlot.java | 18 +-- .../shatteredpixeldungeon/windows/WndBag.java | 2 +- .../windows/WndRanking.java | 15 +-- 9 files changed, 150 insertions(+), 61 deletions(-) create mode 100644 src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/QuickSlot.java diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java b/src/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java index d9a279e14..d7541da81 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java @@ -158,9 +158,6 @@ public class Dungeon { public static Hero hero; public static Level level; - // Either Item or Class - public static Object quickslot; - public static int depth; public static int gold; // Reason of death @@ -512,10 +509,6 @@ public class Dungeon { Journal.storeInBundle( bundle ); Generator.storeInBundle( bundle ); - if (quickslot instanceof Class) { - bundle.put( QUICKSLOT, ((Class)quickslot).getName() ); - } - Scroll.save( bundle ); Potion.save( bundle ); Wand.save( bundle ); @@ -642,16 +635,6 @@ public class Dungeon { Badges.reset(); } - String qsClass = bundle.getString( QUICKSLOT ); - if (qsClass != null) { - try { - quickslot = Class.forName( qsClass ); - } catch (ClassNotFoundException e) { - } - } else { - quickslot = null; - } - hero = null; hero = (Hero)bundle.get( HERO ); diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Belongings.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Belongings.java index 78520bf12..fe822f5f0 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Belongings.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Belongings.java @@ -39,7 +39,9 @@ public class Belongings implements Iterable { private Hero owner; - public Bag backpack; + public Bag backpack; + + public QuickSlot quickslot; public KindOfWeapon weapon = null; public Armor armor = null; @@ -69,6 +71,8 @@ public class Belongings implements Iterable { bundle.put( ARMOR, armor ); bundle.put( MISC1, misc1); bundle.put( MISC2, misc2); + + quickslot.storePlaceholders( bundle ); } public void restoreFromBundle( Bundle bundle ) { @@ -92,6 +96,8 @@ public class Belongings implements Iterable { if (misc2 != null) { misc2.activate( owner ); } + + quickslot.restorePlaceholders(bundle); } @SuppressWarnings("unchecked") diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index f768c9803..145a4a902 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -878,7 +878,7 @@ public class Hero extends Char { if (wand.curCharges < wand.maxCharges && damage > 0) { wand.curCharges++; - if (Dungeon.quickslot == wand) { + if (belongings.quickslot.contains(wand)) { QuickSlot.refresh(); } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java index 37233caa5..b332e11fe 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java @@ -136,9 +136,10 @@ public enum HeroClass { hero.STR = hero.STR + 1; (hero.belongings.weapon = new ShortSword()).identify(); - new Dart( 8 ).identify().collect(); + Dart darts = new Dart( 8 ); + darts.identify().collect(); - Dungeon.quickslot = Dart.class; + hero.belongings.quickslot.setSlot(0, darts); new PotionOfStrength().setKnown(); } @@ -149,7 +150,7 @@ public enum HeroClass { WandOfMagicMissile wand = new WandOfMagicMissile(); wand.identify().collect(); - Dungeon.quickslot = wand; + hero.belongings.quickslot.setSlot(0, wand); new ScrollOfIdentify().setKnown(); } @@ -161,10 +162,11 @@ public enum HeroClass { (hero.belongings.misc1 = cloak).identify(); hero.belongings.misc1.activate( hero ); - new Dart( 8 ).identify().collect(); + Dart darts = new Dart( 8 ); + darts.identify().collect(); - - Dungeon.quickslot = cloak; + hero.belongings.quickslot.setSlot(0, cloak); + hero.belongings.quickslot.setSlot(1, darts); new ScrollOfMagicMapping().setKnown(); } @@ -177,7 +179,7 @@ public enum HeroClass { Boomerang boomerang = new Boomerang(); boomerang.identify().collect(); - Dungeon.quickslot = boomerang; + hero.belongings.quickslot.setSlot(0, boomerang); } public String title() { diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/QuickSlot.java b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/QuickSlot.java new file mode 100644 index 000000000..4cbb0c203 --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/actors/hero/QuickSlot.java @@ -0,0 +1,107 @@ +package com.shatteredpixel.shatteredpixeldungeon.actors.hero; + +import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +/** + * Created by debenhame on 16/01/2015. + */ +public class QuickSlot { + + /** + * Slots contain objects which are also in a player's inventory. + * The one exception to this is when quantity is 0, which can + * happen for a stackable item that has been 'used up', these are refered to a placeholders. + */ + private ArrayList slots = new ArrayList(); + + public void setSlot(int slot, Item item){ + slots.set(slot, item); + } + + public Item getItem(int slot){ + return slots.get(slot); + } + + //TODO: this will currently only get the first occurance of an item, even if it's in multiple slots + //perhaps do not allow duplicate items in quickslots. + public int getSlot(Item item) { + return slots.indexOf(item); + } + + public Boolean isPlaceholder(int slot){ + return slots.get(slot) != null && slots.get(slot).quantity() == 0; + } + + public void clearSlot(int slot){ + setSlot(slot, null); + } + + public void clearItem(Item item){ + for (int i = 0; i < slots.size(); i++) + if (slots.get(i) == item) + clearSlot(i); + } + + public void clear(){ + slots = new ArrayList(); + } + + public boolean contains(Item item){ + return slots.contains(item); + } + + public void replaceSimilar(Item item){ + for (int i = 0; i < slots.size(); i++) + if (item.isSimilar(slots.get(i))) + setSlot( i , item ); + } + + public void convertToPlaceholder(Item item){ + Item placeholder = Item.virtual(item.getClass()); + + if (placeholder != null && slots.contains(item)) + for (int i = 0; i < slots.size(); i++) + if (slots.get(i) == item) + setSlot( i , placeholder ); + } + + private final String PLACEHOLDERS = "placeholders"; + private final String PLACEMENTS = "placements"; + + public void storePlaceholders(Bundle bundle){ + ArrayList placeholders = new ArrayList(slots.size()); + boolean[] placements = new boolean[slots.size()]; + + for (int i = 0; i < slots.size(); i++) + if (isPlaceholder(i)) { + placeholders.add(slots.get(i)); + placements[i] = true; + } + bundle.put( PLACEHOLDERS, placeholders ); + bundle.put( PLACEMENTS, placements ); + } + + //placements array is used as order is preserved while bundling, but exact index is not, so if we + //bundle both the placeholders (which preserves their order) an an array telling us where the placeholders are, + //we can reconstruct them perfectly. + + public void restorePlaceholders(Bundle bundle){ + Collection placeholders = bundle.getCollection(PLACEHOLDERS); + boolean[] placements = bundle.getBooleanArray( PLACEMENTS ); + + int i = 0; + for (Bundlable item : placeholders){ + while (placements[i] == false) i++; + setSlot( i, (Item)item ); + i++; + } + + } + +} diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/Item.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/Item.java index 21af82be5..75734de02 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/items/Item.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/Item.java @@ -177,7 +177,8 @@ public class Item implements Bundlable { Badges.validateItemLevelAquired( this ); } - items.add( this ); + items.add( this ); + Dungeon.hero.belongings.quickslot.replaceSimilar(this); QuickSlot.refresh(); Collections.sort( items, itemComparator ); return true; @@ -203,6 +204,10 @@ public class Item implements Bundlable { } else if (quantity == 1) { + if (stackable == true){ + Dungeon.hero.belongings.quickslot.convertToPlaceholder(this); + } + return detachAll( container ); } else { @@ -232,6 +237,7 @@ public class Item implements Bundlable { if (item == this) { container.items.remove( this ); item.onDetach( ); + Dungeon.hero.belongings.quickslot.clearItem( this ); QuickSlot.refresh(); return this; } else if (item instanceof Bag) { @@ -390,7 +396,7 @@ public class Item implements Bundlable { } public void updateQuickslot() { - if ((stackable && Dungeon.quickslot == getClass()) || Dungeon.quickslot == this) { + if (Dungeon.hero.belongings.quickslot.contains( this )) { QuickSlot.refresh(); } } @@ -400,7 +406,8 @@ public class Item implements Bundlable { private static final String LEVEL_KNOWN = "levelKnown"; private static final String CURSED = "cursed"; private static final String CURSED_KNOWN = "cursedKnown"; - private static final String QUICKSLOT = "quickslot"; + private static final String OLDSLOT = "quickslot"; + private static final String QUICKSLOT = "quickslotpos"; @Override public void storeInBundle( Bundle bundle ) { @@ -409,8 +416,8 @@ public class Item implements Bundlable { bundle.put( LEVEL_KNOWN, levelKnown ); bundle.put( CURSED, cursed ); bundle.put( CURSED_KNOWN, cursedKnown ); - if (this == Dungeon.quickslot) { - bundle.put( QUICKSLOT, true ); + if (Dungeon.hero.belongings.quickslot.contains(this)) { + bundle.put( QUICKSLOT, Dungeon.hero.belongings.quickslot.getSlot(this) ); } } @@ -428,9 +435,12 @@ public class Item implements Bundlable { } cursed = bundle.getBoolean( CURSED ); - - if (bundle.getBoolean( QUICKSLOT )) { - Dungeon.quickslot = this; + + //support for pre-0.2.3 saves and rankings + if (bundle.contains( OLDSLOT )) { + Dungeon.hero.belongings.quickslot.setSlot( 0 , this); + } else if (bundle.contains( QUICKSLOT )) { + Dungeon.hero.belongings.quickslot.setSlot( bundle.getInt( QUICKSLOT ), this); } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/ui/QuickSlot.java b/src/com/shatteredpixel/shatteredpixeldungeon/ui/QuickSlot.java index 9ec306f3d..058a7537c 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/ui/QuickSlot.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/ui/QuickSlot.java @@ -28,6 +28,7 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag; +//TODO: add proper multi-quickslot functionality. public class QuickSlot extends Button implements WndBag.Listener { private static final String TXT_SELECT_ITEM = "Select an item for the quickslot"; @@ -126,20 +127,7 @@ public class QuickSlot extends Button implements WndBag.Listener { @SuppressWarnings("unchecked") private static Item select() { - if (Dungeon.quickslot instanceof Item) { - - return (Item)Dungeon.quickslot; - - } else if (Dungeon.quickslot != null) { - - Item item = Dungeon.hero.belongings.getItem( (Class)Dungeon.quickslot ); - return item != null ? item : Item.virtual( (Class)Dungeon.quickslot ); - - } else { - - return null; - - } + return Dungeon.hero.belongings.quickslot.getItem(0); } public static Item getItem(){ @@ -150,7 +138,7 @@ public class QuickSlot extends Button implements WndBag.Listener { @Override public void onSelect( Item item ) { if (item != null) { - Dungeon.quickslot = item.stackable ? item.getClass() : item; + Dungeon.hero.belongings.quickslot.setSlot( 0 , item ); refresh(); } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java index 36f403e3b..9f47146ff 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndBag.java @@ -395,7 +395,7 @@ public class WndBag extends WndTabbed { protected boolean onLongClick() { if (listener == null && item.defaultAction != null) { hide(); - Dungeon.quickslot = (item instanceof EquipableItem && !item.stackable) ? item : item.getClass(); + Dungeon.hero.belongings.quickslot.setSlot( 0 , item ); QuickSlot.refresh(); return true; } else { diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndRanking.java b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndRanking.java index 2d7e48357..6987ad5a2 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndRanking.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndRanking.java @@ -246,17 +246,10 @@ public class WndRanking extends WndTabbed { if (stuff.misc2 != null) { addItem( stuff.misc2); } - - if (Dungeon.quickslot instanceof Item && - Dungeon.hero.belongings.backpack.contains( (Item)Dungeon.quickslot )) { - - addItem( (Item)Dungeon.quickslot ); - } else if (Dungeon.quickslot instanceof Class){ - @SuppressWarnings("unchecked") - Item item = Dungeon.hero.belongings.getItem( (Class)Dungeon.quickslot ); - if (item != null) { - addItem( item ); - } + + //TODO: add proper visual support for mutli-quickslots + if (stuff.quickslot.getItem(0) != null){ + addItem( stuff.quickslot.getItem(0) ); } }