v1.1.0: converted alchemical energy to a currency like gold

Things still to do:
- add interface for creating alchemical energy
- redesign alchemize spell
- fix toolkit
This commit is contained in:
Evan Debenham 2021-11-12 14:30:24 -05:00
parent f56e1cf498
commit efeda9c5ff
21 changed files with 373 additions and 220 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1678,6 +1678,9 @@ items.equipableitem.unequip_cursed=You can't remove a cursed item!
items.equipableitem.ac_equip=EQUIP items.equipableitem.ac_equip=EQUIP
items.equipableitem.ac_unequip=UNEQUIP items.equipableitem.ac_unequip=UNEQUIP
items.energycrystal.name=energy crystal
items.energycrystal.desc=A collection of small magical crystals, filled with alchemical energy.\n\nThese crystals are the most common ingredient in alchemy recipes and can be produced at an alchemy pot by scrapping consumable items.
items.gold.name=gold items.gold.name=gold
items.gold.desc=A pile of gold coins. Collect gold coins to spend them later in a shop. items.gold.desc=A pile of gold coins. Collect gold coins to spend them later in a shop.

View File

@ -4,7 +4,7 @@ scenes.alchemyscene.title=Alchemy
scenes.alchemyscene.text=Combine ingredients to create something new! scenes.alchemyscene.text=Combine ingredients to create something new!
scenes.alchemyscene.select=Select an item scenes.alchemyscene.select=Select an item
scenes.alchemyscene.cost=Energy: %d scenes.alchemyscene.cost=Energy: %d
scenes.alchemyscene.energy=Alchemical Energy: %d scenes.alchemyscene.energy=Energy: %d
scenes.amuletscene.exit=Let's call it a day scenes.amuletscene.exit=Let's call it a day
scenes.amuletscene.stay=I'm not done yet scenes.amuletscene.stay=I'm not done yet

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -162,7 +162,9 @@ public class Dungeon {
public static QuickSlot quickslot = new QuickSlot(); public static QuickSlot quickslot = new QuickSlot();
public static int depth; public static int depth;
public static int gold; public static int gold;
public static int energy;
public static HashSet<Integer> chapters; public static HashSet<Integer> chapters;
@ -203,6 +205,7 @@ public class Dungeon {
depth = 0; depth = 0;
gold = 0; gold = 0;
energy = 0;
droppedItems = new SparseArray<>(); droppedItems = new SparseArray<>();
portedItems = new SparseArray<>(); portedItems = new SparseArray<>();
@ -443,8 +446,9 @@ public class Dungeon {
private static final String CHALLENGES = "challenges"; private static final String CHALLENGES = "challenges";
private static final String MOBS_TO_CHAMPION = "mobs_to_champion"; private static final String MOBS_TO_CHAMPION = "mobs_to_champion";
private static final String HERO = "hero"; private static final String HERO = "hero";
private static final String GOLD = "gold";
private static final String DEPTH = "depth"; private static final String DEPTH = "depth";
private static final String GOLD = "gold";
private static final String ENERGY = "energy";
private static final String DROPPED = "dropped%d"; private static final String DROPPED = "dropped%d";
private static final String PORTED = "ported%d"; private static final String PORTED = "ported%d";
private static final String LEVEL = "level"; private static final String LEVEL = "level";
@ -463,9 +467,11 @@ public class Dungeon {
bundle.put( CHALLENGES, challenges ); bundle.put( CHALLENGES, challenges );
bundle.put( MOBS_TO_CHAMPION, mobsToChampion ); bundle.put( MOBS_TO_CHAMPION, mobsToChampion );
bundle.put( HERO, hero ); bundle.put( HERO, hero );
bundle.put( GOLD, gold );
bundle.put( DEPTH, depth ); bundle.put( DEPTH, depth );
bundle.put( GOLD, gold );
bundle.put( ENERGY, energy );
for (int d : droppedItems.keyArray()) { for (int d : droppedItems.keyArray()) {
bundle.put(Messages.format(DROPPED, d), droppedItems.get(d)); bundle.put(Messages.format(DROPPED, d), droppedItems.get(d));
} }
@ -609,9 +615,11 @@ public class Dungeon {
hero = null; hero = null;
hero = (Hero)bundle.get( HERO ); hero = (Hero)bundle.get( HERO );
gold = bundle.getInt( GOLD );
depth = bundle.getInt( DEPTH ); depth = bundle.getInt( DEPTH );
gold = bundle.getInt( GOLD );
energy = bundle.getInt( ENERGY );
Statistics.restoreFromBundle( bundle ); Statistics.restoreFromBundle( bundle );
Generator.restoreFromBundle( bundle ); Generator.restoreFromBundle( bundle );

View File

@ -24,10 +24,12 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.blobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.EnergyCrystal;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes; import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.scenes.AlchemyScene; import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
public class Alchemy extends Blob implements AlchemyScene.AlchemyProvider { public class Alchemy extends Blob {
protected int pos; protected int pos;
@ -39,6 +41,17 @@ public class Alchemy extends Blob implements AlchemyScene.AlchemyProvider {
cell = j + i* Dungeon.level.width(); cell = j + i* Dungeon.level.width();
if (Dungeon.level.insideMap(cell)) { if (Dungeon.level.insideMap(cell)) {
off[cell] = cur[cell]; off[cell] = cur[cell];
//for pre-v1.1.0 saves, drops 1/4 the pot's old energy contents in crystals
if (off[cell] >= 1){
int n;
do {
n = cell + PathFinder.NEIGHBOURS8[Random.Int( 8 )];
} while (!Dungeon.level.passable[n] && !Dungeon.level.avoid[n]);
Dungeon.level.drop( new EnergyCrystal((int)Math.ceil(off[cell]/4f)), n ).sprite.drop( cell );
off[cell] = 1;
}
volume += off[cell]; volume += off[cell];
if (off[cell] > 0 && Dungeon.level.heroFOV[cell]){ if (off[cell] > 0 && Dungeon.level.heroFOV[cell]){
Notes.add( Notes.Landmark.ALCHEMY ); Notes.add( Notes.Landmark.ALCHEMY );
@ -54,17 +67,4 @@ public class Alchemy extends Blob implements AlchemyScene.AlchemyProvider {
emitter.start( Speck.factory( Speck.BUBBLE ), 0.33f, 0 ); emitter.start( Speck.factory( Speck.BUBBLE ), 0.33f, 0 );
} }
public static int alchPos;
//1 volume is kept in reserve
@Override
public int getEnergy() {
return Math.max(0, cur[alchPos] - 1);
}
@Override
public void spendEnergy(int reduction) {
cur[alchPos] = Math.max(1, cur[alchPos] - reduction);
}
} }

View File

@ -832,11 +832,6 @@ public class Hero extends Char {
return false; return false;
} }
Alchemy alch = (Alchemy) Dungeon.level.blobs.get(Alchemy.class);
if (alch != null) {
alch.alchPos = dst;
AlchemyScene.setProvider( alch );
}
ShatteredPixelDungeon.switchScene(AlchemyScene.class); ShatteredPixelDungeon.switchScene(AlchemyScene.class);
return false; return false;

View File

@ -0,0 +1,67 @@
package com.shatteredpixel.shatteredpixeldungeon.items;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Random;
import java.util.ArrayList;
public class EnergyCrystal extends Item {
private static final String TXT_VALUE = "%+d";
{
image = ItemSpriteSheet.ENERGY;
stackable = true;
}
public EnergyCrystal() {
this( 1 );
}
public EnergyCrystal( int value ) {
this.quantity = value;
}
@Override
public ArrayList<String> actions(Hero hero ) {
return new ArrayList<>();
}
@Override
public boolean doPickUp( Hero hero ) {
Dungeon.energy += quantity;
//TODO Statistics.goldCollected += quantity;
//Badges.validateGoldCollected();
GameScene.pickUp( this, hero.pos );
hero.sprite.showStatus( 0x44CCFF, TXT_VALUE, quantity );
hero.spendAndNext( TIME_TO_PICK_UP );
Sample.INSTANCE.play( Assets.Sounds.ITEM );
return true;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public Item random() {
quantity = Random.IntRange( 4, 6 );
return this;
}
}

View File

@ -94,17 +94,4 @@ public class Gold extends Item {
return this; return this;
} }
private static final String VALUE = "value";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( VALUE, quantity );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle(bundle);
quantity = bundle.getInt( VALUE );
}
} }

View File

@ -74,7 +74,8 @@ public class AlchemistsToolkit extends Artifact {
else if (hero.visibleEnemies() > hero.mindVisionEnemies.size()) GLog.i( Messages.get(this, "enemy_near") ); else if (hero.visibleEnemies() > hero.mindVisionEnemies.size()) GLog.i( Messages.get(this, "enemy_near") );
else { else {
AlchemyScene.setProvider(hero.buff(kitEnergy.class)); //TODO notify scene we're using a toolkit here instead
//AlchemyScene.setProvider(hero.buff(kitEnergy.class));
Game.switchScene(AlchemyScene.class); Game.switchScene(AlchemyScene.class);
} }
@ -164,7 +165,7 @@ public class AlchemistsToolkit extends Artifact {
alchemyReady = bundle.getBoolean(READY); alchemyReady = bundle.getBoolean(READY);
} }
public class kitEnergy extends ArtifactBuff implements AlchemyScene.AlchemyProvider { public class kitEnergy extends ArtifactBuff {
public void gainCharge(float levelPortion) { public void gainCharge(float levelPortion) {
alchemyReady = true; alchemyReady = true;
@ -198,31 +199,21 @@ public class AlchemistsToolkit extends Artifact {
partialCharge = 0; partialCharge = 0;
} }
@Override
public int getEnergy() {
return charge;
}
@Override
public void spendEnergy(int reduction) {
charge = Math.max(0, charge - reduction);
Talent.onArtifactUsed(Dungeon.hero);
}
} }
//TODO this isn't working with new energy yet, atm it's just sucking up all energy possible
public static class upgradeKit extends Recipe { public static class upgradeKit extends Recipe {
@Override @Override
public boolean testIngredients(ArrayList<Item> ingredients) { public boolean testIngredients(ArrayList<Item> ingredients) {
return ingredients.get(0) instanceof AlchemistsToolkit return ingredients.get(0) instanceof AlchemistsToolkit;
&& !AlchemyScene.providerIsToolkit();
} }
private static int lastCost; private static int lastCost;
@Override @Override
public int cost(ArrayList<Item> ingredients) { public int cost(ArrayList<Item> ingredients) {
return lastCost = Math.max(1, AlchemyScene.availableEnergy()); return lastCost = Math.max(1, Dungeon.energy);
} }
@Override @Override
@ -245,7 +236,7 @@ public class AlchemistsToolkit extends Artifact {
sample.partialCharge = existing.partialCharge; sample.partialCharge = existing.partialCharge;
sample.exp = existing.exp; sample.exp = existing.exp;
sample.level(existing.level()); sample.level(existing.level());
sample.absorbEnergy(AlchemyScene.availableEnergy()); sample.absorbEnergy(Dungeon.energy);
return sample; return sample;
} }
} }

View File

@ -29,7 +29,8 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.AlchemyScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class Alchemize extends Spell implements AlchemyScene.AlchemyProvider { //TODO redesign
public class Alchemize extends Spell {
{ {
image = ItemSpriteSheet.ALCHEMIZE; image = ItemSpriteSheet.ALCHEMIZE;
@ -43,20 +44,10 @@ public class Alchemize extends Spell implements AlchemyScene.AlchemyProvider {
} }
detach( curUser.belongings.backpack ); detach( curUser.belongings.backpack );
updateQuickslot(); updateQuickslot();
AlchemyScene.setProvider(this); //AlchemyScene.setProvider(this);
ShatteredPixelDungeon.switchScene(AlchemyScene.class); ShatteredPixelDungeon.switchScene(AlchemyScene.class);
} }
@Override
public int getEnergy() {
return 0;
}
@Override
public void spendEnergy(int reduction) {
//do nothing
}
@Override @Override
public int value() { public int value() {
//prices of ingredients, divided by output quantity //prices of ingredients, divided by output quantity

View File

@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Alchemy; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Alchemy;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.items.EnergyCrystal;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfExperience; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfExperience;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfFrost; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfFrost;
@ -73,10 +74,15 @@ public class SecretLaboratoryRoom extends SecretRoom {
Blob.seed( pot.x + level.width() * pot.y, 1+Random.NormalIntRange(20, 30), Alchemy.class, level ); Blob.seed( pot.x + level.width() * pot.y, 1+Random.NormalIntRange(20, 30), Alchemy.class, level );
int pos;
do {
pos = level.pointToCell(random());
} while (level.map[pos] != Terrain.EMPTY_SP || level.heaps.get( pos ) != null);
level.drop( new EnergyCrystal().random(), pos );
int n = Random.IntRange( 2, 3 ); int n = Random.IntRange( 2, 3 );
HashMap<Class<? extends Potion>, Float> chances = new HashMap<>(potionChances); HashMap<Class<? extends Potion>, Float> chances = new HashMap<>(potionChances);
for (int i=0; i < n; i++) { for (int i=0; i < n; i++) {
int pos;
do { do {
pos = level.pointToCell(random()); pos = level.pointToCell(random());
} while (level.map[pos] != Terrain.EMPTY_SP || level.heaps.get( pos ) != null); } while (level.map[pos] != Terrain.EMPTY_SP || level.heaps.get( pos ) != null);

View File

@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Alchemy; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Alchemy;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.items.EnergyCrystal;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.journal.AlchemyPage; import com.shatteredpixel.shatteredpixeldungeon.items.journal.AlchemyPage;
@ -62,11 +63,18 @@ public class LaboratoryRoom extends SpecialRoom {
Painter.set( level, pot, Terrain.ALCHEMY ); Painter.set( level, pot, Terrain.ALCHEMY );
int chapter = 1 + Dungeon.depth/5; int chapter = 1 + Dungeon.depth/5;
Blob.seed( pot.x + level.width() * pot.y, 1 + chapter*10 + Random.NormalIntRange(0, 10), Alchemy.class, level ); Blob.seed( pot.x + level.width() * pot.y, 1, Alchemy.class, level );
int n = Random.NormalIntRange( 1, 3 );
for (int i=0; i < n; i++) {
int pos; int pos;
do {
pos = level.pointToCell(random());
} while (
level.map[pos] != Terrain.EMPTY_SP ||
level.heaps.get( pos ) != null);
level.drop( new EnergyCrystal().random(), pos );
int n = Random.NormalIntRange( 1, 2 );
for (int i=0; i < n; i++) {
do { do {
pos = level.pointToCell(random()); pos = level.pointToCell(random());
} while ( } while (
@ -100,7 +108,6 @@ public class LaboratoryRoom extends SpecialRoom {
for (int i = 0; i < pagesToDrop; i++) { for (int i = 0; i < pagesToDrop; i++) {
AlchemyPage p = new AlchemyPage(); AlchemyPage p = new AlchemyPage();
p.page(missingPages.remove(0)); p.page(missingPages.remove(0));
int pos;
do { do {
pos = level.pointToCell(random()); pos = level.pointToCell(random());
} while ( } while (

View File

@ -74,7 +74,10 @@ public class AlchemyScene extends PixelScene {
private Emitter lowerBubbles; private Emitter lowerBubbles;
private SkinnedBlock water; private SkinnedBlock water;
private Image energyIcon;
private RenderedTextBlock energyLeft; private RenderedTextBlock energyLeft;
private IconButton energyAdd;
private RenderedTextBlock energyCost; private RenderedTextBlock energyCost;
private RedButton btnCombine; private RedButton btnCombine;
@ -287,13 +290,25 @@ public class AlchemyScene extends PixelScene {
btnGuide.setRect(0, 0, 20, 20); btnGuide.setRect(0, 0, 20, 20);
add(btnGuide); add(btnGuide);
energyLeft = PixelScene.renderTextBlock(Messages.get(AlchemyScene.class, "energy", availableEnergy()), 9); energyLeft = PixelScene.renderTextBlock(Messages.get(AlchemyScene.class, "energy", Dungeon.energy), 9);
energyLeft.setPos( energyLeft.setPos(
(Camera.main.width - energyLeft.width())/2, (Camera.main.width - energyLeft.width())/2,
Camera.main.height - 5 - energyLeft.height() Camera.main.height - 8 - energyLeft.height()
); );
energyLeft.hardlight(0x44CCFF);
add(energyLeft); add(energyLeft);
energyIcon = Icons.get(Icons.ENERGY);
energyIcon.x = energyLeft.left() - energyIcon.width();
energyIcon.y = energyLeft.top() - (energyIcon.height() - energyLeft.height())/2;
align(energyIcon);
add(energyIcon);
//TODO does nothing currently
energyAdd = new IconButton(Icons.get(Icons.PLUS));
energyAdd.setRect(energyLeft.right(), energyIcon.y, 16, 16);
add(energyAdd);
energyCost = PixelScene.renderTextBlock(6); energyCost = PixelScene.renderTextBlock(6);
add(energyCost); add(energyCost);
@ -384,9 +399,9 @@ public class AlchemyScene extends PixelScene {
energyCost.visible = (cost > 0); energyCost.visible = (cost > 0);
if (cost <= availableEnergy()) { if (cost <= Dungeon.energy) {
btnCombine.enable(true); btnCombine.enable(true);
energyCost.resetColor(); energyCost.hardlight(0x44CCFF);
} else { } else {
btnCombine.enable(false); btnCombine.enable(false);
energyCost.hardlight(0xFF0000); energyCost.hardlight(0xFF0000);
@ -408,13 +423,19 @@ public class AlchemyScene extends PixelScene {
Item result = null; Item result = null;
if (recipe != null){ if (recipe != null){
provider.spendEnergy(recipe.cost(ingredients)); Dungeon.energy -= recipe.cost(ingredients);
energyLeft.text(Messages.get(AlchemyScene.class, "energy", availableEnergy())); energyLeft.text(Messages.get(AlchemyScene.class, "energy", Dungeon.energy));
energyLeft.setPos( energyLeft.setPos(
(Camera.main.width - energyLeft.width())/2, (Camera.main.width - energyLeft.width())/2,
Camera.main.height - 5 - energyLeft.height() Camera.main.height - 8 - energyLeft.height()
); );
energyIcon.x = energyLeft.left() - energyIcon.width();
energyIcon.y = energyLeft.top() - (energyIcon.height() - energyLeft.height())/2;
align(energyIcon);
energyAdd.setRect(energyLeft.right(), energyIcon.y, 16, 16);
result = recipe.brew(ingredients); result = recipe.brew(ingredients);
} }
@ -573,25 +594,6 @@ public class AlchemyScene extends PixelScene {
} }
} }
private static AlchemyProvider provider; //TODO add code here for the toolkit's energy
public static void setProvider( AlchemyProvider p ){
provider = p;
}
public static int availableEnergy(){
return provider == null ? 0 : provider.getEnergy();
}
public static boolean providerIsToolkit(){
return provider instanceof AlchemistsToolkit.kitEnergy;
}
public interface AlchemyProvider {
int getEnergy();
void spendEnergy(int reduction);
} }
}

View File

@ -81,18 +81,22 @@ public class ItemSpriteSheet {
private static final int UNCOLLECTIBLE = xy(1, 2); //16 slots private static final int UNCOLLECTIBLE = xy(1, 2); //16 slots
public static final int GOLD = UNCOLLECTIBLE+0; public static final int GOLD = UNCOLLECTIBLE+0;
public static final int DEWDROP = UNCOLLECTIBLE+1; public static final int ENERGY = UNCOLLECTIBLE+1;
public static final int PETAL = UNCOLLECTIBLE+2;
public static final int SANDBAG = UNCOLLECTIBLE+3;
public static final int SPIRIT_ARROW = UNCOLLECTIBLE+4;
public static final int GUIDE_PAGE = UNCOLLECTIBLE+6; public static final int DEWDROP = UNCOLLECTIBLE+3;
public static final int ALCH_PAGE = UNCOLLECTIBLE+7; public static final int PETAL = UNCOLLECTIBLE+4;
public static final int SANDBAG = UNCOLLECTIBLE+5;
public static final int SPIRIT_ARROW = UNCOLLECTIBLE+6;
public static final int TENGU_BOMB = UNCOLLECTIBLE+9; public static final int GUIDE_PAGE = UNCOLLECTIBLE+8;
public static final int TENGU_SHOCKER = UNCOLLECTIBLE+10; public static final int ALCH_PAGE = UNCOLLECTIBLE+9;
public static final int TENGU_BOMB = UNCOLLECTIBLE+11;
public static final int TENGU_SHOCKER = UNCOLLECTIBLE+12;
static{ static{
assignItemRect(GOLD, 15, 13); assignItemRect(GOLD, 15, 13);
assignItemRect(ENERGY, 16, 16);
assignItemRect(DEWDROP, 10, 10); assignItemRect(DEWDROP, 10, 10);
assignItemRect(PETAL, 8, 8); assignItemRect(PETAL, 8, 8);
assignItemRect(SANDBAG, 10, 10); assignItemRect(SANDBAG, 10, 10);

View File

@ -0,0 +1,120 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2021 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 <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.ui;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.Game;
import com.watabou.noosa.ui.Component;
public class CurrencyIndicator extends Component {
private static final float TIME = 2f;
private int lastGold = 0;
private int lastEnergy = 0;
private BitmapText gold;
private BitmapText energy;
private float goldTime;
private float energyTime;
@Override
protected void createChildren() {
gold = new BitmapText( PixelScene.pixelFont);
add( gold );
energy = new BitmapText( PixelScene.pixelFont);
add( energy );
gold.visible = energy.visible = false;
}
@Override
protected void layout() {
gold.x = x + (width - gold.width()) / 2;
gold.y = bottom() - gold.height();
energy.x = x + (width - energy.width()) / 2;
if (gold.visible) {
energy.y = bottom() - energy.height() - gold.height() + 2;
} else {
energy.y = bottom() - energy.height();
}
}
@Override
public void update() {
super.update();
if (gold.visible) {
goldTime -= Game.elapsed;
if (goldTime > 0) {
gold.alpha( goldTime > TIME / 2 ? 1f : goldTime * 2 / TIME );
} else {
gold.visible = false;
}
}
if (energy.visible) {
energyTime -= Game.elapsed;
if (energyTime > 0) {
energy.alpha( energyTime > TIME / 2 ? 1f : energyTime * 2 / TIME );
} else {
energy.visible = false;
}
}
if (Dungeon.gold != lastGold) {
lastGold = Dungeon.gold;
gold.text( Integer.toString(lastGold) );
gold.measure();
gold.hardlight( 0xFFFF00 );
gold.visible = true;
goldTime = TIME;
layout();
}
if (Dungeon.energy != lastEnergy) {
lastEnergy = Dungeon.energy;
energy.text( Integer.toString(lastEnergy) );
energy.measure();
energy.hardlight( 0x44CCFF );
energy.visible = true;
energyTime = TIME;
layout();
}
}
}

View File

@ -1,83 +0,0 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2021 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 <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.ui;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.Game;
import com.watabou.noosa.ui.Component;
public class GoldIndicator extends Component {
private static final float TIME = 2f;
private int lastValue = 0;
private BitmapText tf;
private float time;
@Override
protected void createChildren() {
tf = new BitmapText( PixelScene.pixelFont);
tf.hardlight( 0xFFFF00 );
add( tf );
visible = false;
}
@Override
protected void layout() {
tf.x = x + (width - tf.width()) / 2;
tf.y = bottom() - tf.height();
}
@Override
public void update() {
super.update();
if (visible) {
time -= Game.elapsed;
if (time > 0) {
tf.alpha( time > TIME / 2 ? 1f : time * 2 / TIME );
} else {
visible = false;
}
}
if (Dungeon.gold != lastValue) {
lastValue = Dungeon.gold;
tf.text( Integer.toString( lastValue ) );
tf.measure();
visible = true;
time = TIME;
layout();
}
}
}

View File

@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.watabou.noosa.Image; import com.watabou.noosa.Image;
//TODO the icons asset is getting pretty bloated, should expand the texture and reorganize
public enum Icons { public enum Icons {
//button icons //button icons
@ -46,6 +47,7 @@ public enum Icons {
MAGNIFY, MAGNIFY,
BUFFS, BUFFS,
BACKPACK_LRG, BACKPACK_LRG,
PLUS,
//ingame UI icons //ingame UI icons
SKULL, SKULL,
@ -58,8 +60,11 @@ public enum Icons {
BACKPACK, BACKPACK,
SEED_POUCH, SEED_POUCH,
SCROLL_HOLDER, SCROLL_HOLDER,
POTION_BANDOLIER,
WAND_HOLSTER, WAND_HOLSTER,
POTION_BANDOLIER,
ENERGY,
COIN_SML,
ENERGY_SML,
//hero & rankings icons //hero & rankings icons
DEPTH, DEPTH,
@ -150,6 +155,9 @@ public enum Icons {
case BACKPACK_LRG: case BACKPACK_LRG:
icon.frame( icon.texture.uvRect( 64, 80, 80, 96 ) ); icon.frame( icon.texture.uvRect( 64, 80, 80, 96 ) );
break; break;
case PLUS:
icon.frame( icon.texture.uvRect( 80, 80, 91, 91 ) );
break;
case SKULL: case SKULL:
icon.frame( icon.texture.uvRect( 0, 32, 8, 40 ) ); icon.frame( icon.texture.uvRect( 0, 32, 8, 40 ) );
@ -187,6 +195,15 @@ public enum Icons {
case POTION_BANDOLIER: case POTION_BANDOLIER:
icon.frame( icon.texture.uvRect( 88, 32, 98, 42 ) ); icon.frame( icon.texture.uvRect( 88, 32, 98, 42 ) );
break; break;
case ENERGY:
icon.frame( icon.texture.uvRect( 96, 80, 112, 96 ) );
break;
case COIN_SML:
icon.frame( icon.texture.uvRect( 112, 80, 119, 87 ) );
break;
case ENERGY_SML:
icon.frame( icon.texture.uvRect( 112, 88, 120, 95 ) );
break;
case DEPTH: case DEPTH:
icon.frame( icon.texture.uvRect( 0, 48, 13, 64 ) ); icon.frame( icon.texture.uvRect( 0, 48, 13, 64 ) );

View File

@ -133,7 +133,7 @@ public class QuickRecipe extends Component {
if (cost > 0) { if (cost > 0) {
arrow = new arrow(Icons.get(Icons.ARROW), cost); arrow = new arrow(Icons.get(Icons.ARROW), cost);
arrow.hardlightText(0x00CCFF); arrow.hardlightText(0x44CCFF);
} else { } else {
arrow = new arrow(Icons.get(Icons.ARROW)); arrow = new arrow(Icons.get(Icons.ARROW));
} }

View File

@ -139,7 +139,7 @@ public class Toolbar extends Component {
}); });
add(btnInventory = new Tool(0, 0, 24, 26) { add(btnInventory = new Tool(0, 0, 24, 26) {
private GoldIndicator gold; private CurrencyIndicator ind;
@Override @Override
protected void onClick() { protected void onClick() {
@ -160,14 +160,14 @@ public class Toolbar extends Component {
@Override @Override
protected void createChildren() { protected void createChildren() {
super.createChildren(); super.createChildren();
gold = new GoldIndicator(); ind = new CurrencyIndicator();
add(gold); add(ind);
} }
@Override @Override
protected void layout() { protected void layout() {
super.layout(); super.layout();
gold.fill(this); ind.fill(this);
} }
}); });

View File

@ -168,25 +168,63 @@ public class WndBag extends WndTabbed {
protected void placeTitle( Bag bag, int width ){ protected void placeTitle( Bag bag, int width ){
float titleWidth;
if (Dungeon.energy == 0) {
ItemSprite gold = new ItemSprite(ItemSpriteSheet.GOLD, null); ItemSprite gold = new ItemSprite(ItemSpriteSheet.GOLD, null);
gold.x = width - gold.width() - 1; gold.x = width - gold.width();
gold.y = (TITLE_HEIGHT - gold.height())/2f - 1; gold.y = (TITLE_HEIGHT - gold.height()) / 2f;
PixelScene.align(gold); PixelScene.align(gold);
add(gold); add(gold);
BitmapText amt = new BitmapText(Integer.toString(Dungeon.gold), PixelScene.pixelFont); BitmapText amt = new BitmapText(Integer.toString(Dungeon.gold), PixelScene.pixelFont);
amt.hardlight(TITLE_COLOR); amt.hardlight(TITLE_COLOR);
amt.measure(); amt.measure();
amt.x = width - gold.width() - amt.width() - 2; amt.x = width - gold.width() - amt.width() - 1;
amt.y = (TITLE_HEIGHT - amt.baseLine()) / 2f - 1; amt.y = (TITLE_HEIGHT - amt.baseLine()) / 2f - 1;
PixelScene.align(amt); PixelScene.align(amt);
add(amt); add(amt);
titleWidth = amt.x;
} else {
Image gold = Icons.get(Icons.COIN_SML);
gold.x = width - gold.width() - 0.5f;
gold.y = 0;
PixelScene.align(gold);
add(gold);
BitmapText amt = new BitmapText(Integer.toString(Dungeon.gold), PixelScene.pixelFont);
amt.hardlight(TITLE_COLOR);
amt.measure();
amt.x = width - gold.width() - amt.width() - 2f;
amt.y = 0;
PixelScene.align(amt);
add(amt);
titleWidth = amt.x;
Image energy = Icons.get(Icons.ENERGY_SML);
energy.x = width - energy.width();
energy.y = gold.height();
PixelScene.align(energy);
add(energy);
amt = new BitmapText(Integer.toString(Dungeon.energy), PixelScene.pixelFont);
amt.hardlight(0x44CCFF);
amt.measure();
amt.x = width - energy.width() - amt.width() - 1;
amt.y = energy.y;
PixelScene.align(amt);
add(amt);
titleWidth = Math.min(titleWidth, amt.x);
}
String title = selector != null ? selector.textPrompt() : null; String title = selector != null ? selector.textPrompt() : null;
RenderedTextBlock txtTitle = PixelScene.renderTextBlock( RenderedTextBlock txtTitle = PixelScene.renderTextBlock(
title != null ? Messages.titleCase(title) : Messages.titleCase( bag.name() ), 8 ); title != null ? Messages.titleCase(title) : Messages.titleCase( bag.name() ), 8 );
txtTitle.hardlight( TITLE_COLOR ); txtTitle.hardlight( TITLE_COLOR );
txtTitle.maxWidth( (int)amt.x - 2 ); txtTitle.maxWidth( (int)titleWidth - 2 );
txtTitle.setPos( txtTitle.setPos(
1, 1,
(TITLE_HEIGHT - txtTitle.height()) / 2f - 1 (TITLE_HEIGHT - txtTitle.height()) / 2f - 1