v2.2.0: implemented new rewards for the blacksmith quest

This commit is contained in:
Evan Debenham
2023-08-23 15:01:41 -04:00
parent d2b8bc5dab
commit de86487aaa
10 changed files with 488 additions and 251 deletions

View File

@@ -977,12 +977,6 @@ actors.mobs.npcs.blacksmith.exit_warn_gnoll=That gnoll geomancer's still down th
actors.mobs.npcs.blacksmith.exit_yes=I'm Done
actors.mobs.npcs.blacksmith.exit_no=Not Yet
actors.mobs.npcs.blacksmith.get_lost=I'm busy. Get lost!
actors.mobs.npcs.blacksmith.same_item=Select 2 different items, not the same item twice!
actors.mobs.npcs.blacksmith.diff_type=Select 2 items of the same type!
actors.mobs.npcs.blacksmith.un_ided=I need to know what I'm working with, identify them first!
actors.mobs.npcs.blacksmith.cursed=I don't work with cursed items!
actors.mobs.npcs.blacksmith.degraded=It's junk, the quality is too poor!
actors.mobs.npcs.blacksmith.cant_reforge=I can't reforge these items!
actors.mobs.npcs.blacksmith.entrance_blocked=The way down is blocked.
actors.mobs.npcs.blacksmith.cant_enter_old=That area is not accessible on this run. Play a new game to try the new quest!
actors.mobs.npcs.blacksmith.def_verb=blocked

View File

@@ -77,6 +77,7 @@ items.armor.armor.ac_detach=DETACH
items.armor.armor.detach_seal=You detach the seal from your armor.
items.armor.armor.equip_cursed=The armor constricts around you painfully.
items.armor.armor.identify=You are now familiar enough with your armor to identify it.
items.armor.armor.hardening_gone=The hardening on this armor has worn off!
items.armor.armor.incompatible=Interaction of different types of magic has erased the glyph on this armor!
items.armor.armor.curr_absorb=This _tier-%1$d_ armor blocks _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly.
items.armor.armor.avg_absorb=Typically this _tier-%1$d_ armor blocks _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly.
@@ -86,6 +87,8 @@ items.armor.armor.excess_str=Because of your excess strength, you are _more evas
items.armor.armor.evasion=It is augmented to enhance _evasion._
items.armor.armor.defense=It is augmented to enhance _defense._
items.armor.armor.inscribed=it is inscribed with a _%s._
items.armor.armor.glyph_hardened=It has been _hardened._
items.armor.armor.hardened_no_glyph=This armor has been _hardened,_ but is not currently inscribed with a glyph.
items.armor.armor.cursed_worn=Because this armor is cursed, you are powerless to remove it.
items.armor.armor.cursed=You can feel a malevolent magic lurking within this armor.
items.armor.armor.weak_cursed=Despite the curse, you are able to unequip this armor.
@@ -1877,6 +1880,7 @@ items.weapon.spiritbow.desc=A bow made out of ancient magical wood. The bow's st
items.weapon.weapon.identify=You are now familiar enough with your weapon to identify it.
items.weapon.weapon.too_heavy=Because of your inadequate strength this weapon will hinder your attack speed, accuracy, and ability to surprise attack.
items.weapon.weapon.excess_str=Because of your excess strength, you will deal up to _%d bonus damage_ with this weapon.
items.weapon.weapon.hardening_gone=The hardening on this weapon has worn off!
items.weapon.weapon.incompatible=Interaction of different types of magic has negated the enchantment on this weapon!
items.weapon.weapon.cursed_worn=Because this weapon is cursed, you are powerless to remove it.
items.weapon.weapon.cursed=You can feel a malevolent magic lurking within this weapon.
@@ -1885,6 +1889,8 @@ items.weapon.weapon.not_cursed=This weapon is free of malevolent magic.
items.weapon.weapon.faster=It is augmented to enhance _speed._
items.weapon.weapon.stronger=It is augmented to enhance _damage._
items.weapon.weapon.enchanted=it has a _%s._
items.weapon.weapon.enchant_hardened=It has been _hardened._
items.weapon.weapon.hardened_no_enchant=This weapon has been _hardened,_ but is not currently enchanted.
items.weapon.weapon$enchantment.enchant=enchantment

View File

@@ -1,6 +1,16 @@
windows.wndblacksmithold.prompt=Ok, a deal is a deal, here's what I can do for you: I can reforge 2 items and turn them into one of a better quality.
windows.wndblacksmithold.select=Reforge an item
windows.wndblacksmithold.reforge=Reforge them
windows.wndblacksmith.prompt=Okay, a deal's a deal. Here's what I can do for you.\n\n_Current Favor: %d_
windows.wndblacksmith.pickaxe=_Pickaxe (%d favor):_ I guess I can give you the pickaxe back if you want. I've got plenty more.
windows.wndblacksmith.reforge=_Reforge (%d favor):_ I can reforge two of the same type of identified item into one of a higher quality.
windows.wndblacksmith.harden=_Harden (%d favor):_ I can harden an identified weapon or armor, so it's easier to keep an enchantment or glyph.
windows.wndblacksmith.upgrade=_Upgrade (%d favor):_ If you've got an identified item below +3 I can upgrade it for you.
windows.wndblacksmith.smith=_Smith (%d favor):_ I can try forging a weapon or armor for you from scratch. It'll be higher tier and probably upgraded, and you'll get some choice over what you get.
windows.wndblacksmith.cashout=_Cash Out (%d favor):_ I can just give you some regular gold I've got lyin' around.
windows.wndblacksmith$wndreforge.message=Okay, I can reforge two identified items of the same type and turn them into one of a better quality.
windows.wndblacksmith$wndreforge.prompt=Reforge an item
windows.wndblacksmith$wndreforge.reforge=Reforge them
windows.wndblacksmith$hardenselector.prompt=Harden an item
windows.wndblacksmith$upgradeselector.prompt=Upgrade an item
windows.wndblacksmith$wndsmith.prompt=Okay, here's what I can make. I've already got the forge fired up so choose quickly.
windows.wndchallenges.title=Challenges

View File

@@ -21,21 +21,14 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AscensionChallenge;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.items.BrokenSeal;
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.quest.DarkGold;
import com.shatteredpixel.shatteredpixeldungeon.items.quest.Pickaxe;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.BlacksmithRoom;
@@ -44,10 +37,8 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.BlacksmithSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBlacksmith;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBlacksmithOld;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
@@ -203,7 +194,7 @@ public class Blacksmith extends NPC {
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndBlacksmithOld( Blacksmith.this, Dungeon.hero ) );
GameScene.show( new WndBlacksmith.WndReforge( Blacksmith.this, Dungeon.hero ) );
}
});
@@ -233,85 +224,7 @@ public class Blacksmith extends NPC {
}
});
}
public static String verify( Item item1, Item item2 ) {
if (item1 == item2 && (item1.quantity() == 1 && item2.quantity() == 1)) {
return Messages.get(Blacksmith.class, "same_item");
}
if (item1.getClass() != item2.getClass()) {
return Messages.get(Blacksmith.class, "diff_type");
}
if (!item1.isIdentified() || !item2.isIdentified()) {
return Messages.get(Blacksmith.class, "un_ided");
}
if (item1.cursed || item2.cursed ||
(item1 instanceof Armor && ((Armor) item1).hasCurseGlyph()) ||
(item2 instanceof Armor && ((Armor) item2).hasCurseGlyph()) ||
(item1 instanceof Weapon && ((Weapon) item1).hasCurseEnchant()) ||
(item2 instanceof Weapon && ((Weapon) item2).hasCurseEnchant())) {
return Messages.get(Blacksmith.class, "cursed");
}
if (item1.level() < 0 || item2.level() < 0) {
return Messages.get(Blacksmith.class, "degraded");
}
if (!item1.isUpgradable() || !item2.isUpgradable()) {
return Messages.get(Blacksmith.class, "cant_reforge");
}
return null;
}
public static void upgrade( Item item1, Item item2 ) {
Item first, second;
if (item2.trueLevel() > item1.trueLevel()) {
first = item2;
second = item1;
} else {
first = item1;
second = item2;
}
Sample.INSTANCE.play( Assets.Sounds.EVOKE );
ScrollOfUpgrade.upgrade( Dungeon.hero );
Item.evoke( Dungeon.hero );
if (second.isEquipped( Dungeon.hero )) {
((EquipableItem)second).doUnequip( Dungeon.hero, false );
}
second.detach( Dungeon.hero.belongings.backpack );
if (second instanceof Armor){
BrokenSeal seal = ((Armor) second).checkSeal();
if (seal != null){
Dungeon.level.drop( seal, Dungeon.hero.pos );
}
}
//preserves enchant/glyphs if present
if (first instanceof Weapon && ((Weapon) first).hasGoodEnchant()){
((Weapon) first).upgrade(true);
} else if (first instanceof Armor && ((Armor) first).hasGoodGlyph()){
((Armor) first).upgrade(true);
} else {
first.upgrade();
}
Dungeon.hero.spendAndNext( 2f );
Badges.validateItemLevelAquired( first );
Item.updateQuickslot();
Quest.reforges++;
if (Quest.type != 0) {
Quest.favor -= 500;
}
}
@Override
public int defenseSkill( Char enemy ) {
return INFINITE_EVASION;

View File

@@ -104,6 +104,7 @@ public class Armor extends EquipableItem {
public Augment augment = Augment.NONE;
public Glyph glyph;
public boolean glyphHardened = false;
public boolean curseInfusionBonus = false;
public boolean masteryPotionBonus = false;
@@ -122,6 +123,7 @@ public class Armor extends EquipableItem {
private static final String USES_LEFT_TO_ID = "uses_left_to_id";
private static final String AVAILABLE_USES = "available_uses";
private static final String GLYPH = "glyph";
private static final String GLYPH_HARDENED = "glyph_hardened";
private static final String CURSE_INFUSION_BONUS = "curse_infusion_bonus";
private static final String MASTERY_POTION_BONUS = "mastery_potion_bonus";
private static final String SEAL = "seal";
@@ -133,6 +135,7 @@ public class Armor extends EquipableItem {
bundle.put( USES_LEFT_TO_ID, usesLeftToID );
bundle.put( AVAILABLE_USES, availableUsesToID );
bundle.put( GLYPH, glyph );
bundle.put( GLYPH_HARDENED, glyphHardened );
bundle.put( CURSE_INFUSION_BONUS, curseInfusionBonus );
bundle.put( MASTERY_POTION_BONUS, masteryPotionBonus );
bundle.put( SEAL, seal);
@@ -145,6 +148,7 @@ public class Armor extends EquipableItem {
usesLeftToID = bundle.getInt( USES_LEFT_TO_ID );
availableUsesToID = bundle.getInt( AVAILABLE_USES );
inscribe((Glyph) bundle.get(GLYPH));
glyphHardened = bundle.getBoolean(GLYPH_HARDENED);
curseInfusionBonus = bundle.getBoolean( CURSE_INFUSION_BONUS );
masteryPotionBonus = bundle.getBoolean( MASTERY_POTION_BONUS );
seal = (BrokenSeal)bundle.get(SEAL);
@@ -393,11 +397,21 @@ public class Armor extends EquipableItem {
if (glyph == null){
inscribe( Glyph.random() );
}
} else {
if (hasCurseGlyph()){
} else if (glyph != null) {
//chance to lose harden buff is 10/20/40/80/100% when upgrading from +6/7/8/9/10
if (glyphHardened) {
if (level() >= 6 && Random.Float(10) < Math.pow(2, level()-6)){
glyphHardened = false;
}
//chance to remove curse is a static 33%
} else if (hasCurseGlyph()){
if (Random.Int(3) == 0) inscribe(null);
//otherwise chance to lose glyph is 10/20/40/80/100% when upgrading from +4/5/6/7/8
} else {
//the chance from +4/5, and then +6 can be set to 0% with metamorphed runic transference
int lossChanceStart = 4;
if (Dungeon.hero != null && Dungeon.hero.heroClass != HeroClass.WARRIOR && Dungeon.hero.hasTalent(Talent.RUNIC_TRANSFERENCE)){
lossChanceStart += 1+Dungeon.hero.pointsInTalent(Talent.RUNIC_TRANSFERENCE);
@@ -491,7 +505,10 @@ public class Armor extends EquipableItem {
if (glyph != null && (cursedKnown || !glyph.curse())) {
info += "\n\n" + Messages.capitalize(Messages.get(Armor.class, "inscribed", glyph.name()));
if (glyphHardened) info += " " + Messages.get(Armor.class, "glyph_hardened");
info += " " + glyph.desc();
} else if (glyphHardened){
info += "\n\n" + Messages.get(Armor.class, "hardened_no_glyph");
}
if (cursed && isEquipped( Dungeon.hero )) {

View File

@@ -65,6 +65,7 @@ public class ScrollOfUpgrade extends InventoryScroll {
if (item instanceof Weapon){
Weapon w = (Weapon) item;
boolean wasCursed = w.cursed;
boolean wasHardened = w.enchantHardened;
boolean hadCursedEnchant = w.hasCurseEnchant();
boolean hadGoodEnchant = w.hasGoodEnchant();
@@ -75,13 +76,16 @@ public class ScrollOfUpgrade extends InventoryScroll {
} else if (w.cursedKnown && wasCursed && !w.cursed){
weakenCurse( Dungeon.hero );
}
if (hadGoodEnchant && !w.hasGoodEnchant()){
if (wasHardened && !w.enchantHardened){
GLog.w( Messages.get(Weapon.class, "hardening_gone") );
} else if (hadGoodEnchant && !w.hasGoodEnchant()){
GLog.w( Messages.get(Weapon.class, "incompatible") );
}
} else if (item instanceof Armor){
Armor a = (Armor) item;
boolean wasCursed = a.cursed;
boolean wasHardened = a.glyphHardened;
boolean hadCursedGlyph = a.hasCurseGlyph();
boolean hadGoodGlyph = a.hasGoodGlyph();
@@ -92,7 +96,9 @@ public class ScrollOfUpgrade extends InventoryScroll {
} else if (a.cursedKnown && wasCursed && !a.cursed){
weakenCurse( Dungeon.hero );
}
if (hadGoodGlyph && !a.hasGoodGlyph()){
if (wasHardened && !a.glyphHardened){
GLog.w( Messages.get(Armor.class, "hardening_gone") );
} else if (hadGoodGlyph && !a.hasGoodGlyph()){
GLog.w( Messages.get(Armor.class, "incompatible") );
}

View File

@@ -103,6 +103,7 @@ abstract public class Weapon extends KindOfWeapon {
private float availableUsesToID = USES_TO_ID/2f;
public Enchantment enchantment;
public boolean enchantHardened = false;
public boolean curseInfusionBonus = false;
public boolean masteryPotionBonus = false;
@@ -138,6 +139,7 @@ abstract public class Weapon extends KindOfWeapon {
private static final String USES_LEFT_TO_ID = "uses_left_to_id";
private static final String AVAILABLE_USES = "available_uses";
private static final String ENCHANTMENT = "enchantment";
private static final String ENCHANT_HARDENED = "enchant_hardened";
private static final String CURSE_INFUSION_BONUS = "curse_infusion_bonus";
private static final String MASTERY_POTION_BONUS = "mastery_potion_bonus";
private static final String AUGMENT = "augment";
@@ -148,6 +150,7 @@ abstract public class Weapon extends KindOfWeapon {
bundle.put( USES_LEFT_TO_ID, usesLeftToID );
bundle.put( AVAILABLE_USES, availableUsesToID );
bundle.put( ENCHANTMENT, enchantment );
bundle.put( ENCHANT_HARDENED, enchantHardened );
bundle.put( CURSE_INFUSION_BONUS, curseInfusionBonus );
bundle.put( MASTERY_POTION_BONUS, masteryPotionBonus );
bundle.put( AUGMENT, augment );
@@ -159,6 +162,7 @@ abstract public class Weapon extends KindOfWeapon {
usesLeftToID = bundle.getFloat( USES_LEFT_TO_ID );
availableUsesToID = bundle.getFloat( AVAILABLE_USES );
enchantment = (Enchantment)bundle.get( ENCHANTMENT );
enchantHardened = bundle.getBoolean( ENCHANT_HARDENED );
curseInfusionBonus = bundle.getBoolean( CURSE_INFUSION_BONUS );
masteryPotionBonus = bundle.getBoolean( MASTERY_POTION_BONUS );
@@ -268,9 +272,18 @@ abstract public class Weapon extends KindOfWeapon {
if (enchantment == null){
enchant(Enchantment.random());
}
} else {
if (hasCurseEnchant()){
} else if (enchantment != null) {
//chance to lose harden buff is 10/20/40/80/100% when upgrading from +6/7/8/9/10
if (enchantHardened){
if (level() >= 6 && Random.Float(10) < Math.pow(2, level()-6)){
enchantHardened = false;
}
//chance to remove curse is a static 33%
} else if (hasCurseEnchant()) {
if (Random.Int(3) == 0) enchant(null);
//otherwise chance to lose enchant is 10/20/40/80/100% when upgrading from +4/5/6/7/8
} else if (level() >= 4 && Random.Float(10) < Math.pow(2, level()-4)){
enchant(null);
}

View File

@@ -387,7 +387,10 @@ public class MeleeWeapon extends Weapon {
if (enchantment != null && (cursedKnown || !enchantment.curse())){
info += "\n\n" + Messages.capitalize(Messages.get(Weapon.class, "enchanted", enchantment.name()));
if (enchantHardened) info += " " + Messages.get(Weapon.class, "enchant_hardened");
info += " " + enchantment.desc();
} else if (enchantHardened){
info += "\n\n" + Messages.get(Weapon.class, "hardened_no_enchant");
}
if (cursed && isEquipped( Dungeon.hero )) {

View File

@@ -21,15 +21,33 @@
package com.shatteredpixel.shatteredpixeldungeon.windows;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.items.BrokenSeal;
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
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.scrolls.ScrollOfUpgrade;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.ui.ItemButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Random;
import java.util.ArrayList;
@@ -40,8 +58,7 @@ public class WndBlacksmith extends Window {
private static final int GAP = 2;
//A LOT still to do here!
public WndBlacksmith(Blacksmith troll, Hero hero ) {
public WndBlacksmith( Blacksmith troll, Hero hero ) {
super();
int width = PixelScene.landscape() ? WIDTH_L : WIDTH_P;
@@ -52,30 +69,83 @@ public class WndBlacksmith extends Window {
titlebar.setRect( 0, 0, width, 0 );
add( titlebar );
RenderedTextBlock message = PixelScene.renderTextBlock( Messages.get(this, "prompt"), 6 );
RenderedTextBlock message = PixelScene.renderTextBlock( Messages.get(this, "prompt", Blacksmith.Quest.favor), 6 );
message.maxWidth( width );
message.setPos(0, titlebar.bottom() + GAP);
add( message );
ArrayList<RedButton> buttons = new ArrayList<>();
//TODO
RedButton pickaxe = new RedButton("_Pickaxe (250 favor):_ \"I guess I can give you the pickaxe back if you really want it. I've got plenty more.\"", 6){
int pickaxeCost = Statistics.questScores[2] >= 2500 ? 0 : 250;
RedButton pickaxe = new RedButton(Messages.get(this, "pickaxe", pickaxeCost), 6){
@Override
protected void onClick() {
Blacksmith.Quest.pickaxe.collect(Dungeon.hero.belongings.backpack);
Blacksmith.Quest.favor -= 250;
if (Blacksmith.Quest.pickaxe.doPickUp( Dungeon.hero )) {
GLog.i( Messages.capitalize(Messages.get(Dungeon.hero, "you_now_have", Blacksmith.Quest.pickaxe.name()) ));
} else {
Dungeon.level.drop( Blacksmith.Quest.pickaxe, Dungeon.hero.pos ).sprite.drop();
}
Blacksmith.Quest.favor -= pickaxeCost;
Blacksmith.Quest.pickaxe = null;
WndBlacksmith.this.hide();
if (Blacksmith.Quest.favor > 0) {
GameScene.show(new WndBlacksmith(troll, hero));
}
}
};
pickaxe.enable(Blacksmith.Quest.pickaxe != null && Blacksmith.Quest.favor >= 250);
pickaxe.enable(Blacksmith.Quest.pickaxe != null && Blacksmith.Quest.favor >= pickaxeCost);
buttons.add(pickaxe);
int reforgecost = 500 * (int)Math.pow(2, Blacksmith.Quest.reforges);
RedButton reforge = new RedButton(Messages.get(this, "reforge", reforgecost), 6){
@Override
protected void onClick() {
WndBlacksmith.this.hide();
GameScene.show(new WndReforge(troll, hero));
}
};
reforge.enable(Blacksmith.Quest.favor >= reforgecost);
buttons.add(reforge);
int hardenCost = 500 * (int)Math.pow(2, Blacksmith.Quest.hardens);
RedButton harden = new RedButton(Messages.get(this, "harden", hardenCost), 6){
@Override
protected void onClick() {
GameScene.selectItem(new HardenSelector());
}
};
harden.enable(Blacksmith.Quest.favor >= hardenCost);
buttons.add(harden);
int upgradeCost = 1000 * (int)Math.pow(2, Blacksmith.Quest.upgrades);
RedButton upgrade = new RedButton(Messages.get(this, "upgrade", upgradeCost), 6){
@Override
protected void onClick() {
GameScene.selectItem(new UpgradeSelector());
}
};
upgrade.enable(Blacksmith.Quest.favor >= upgradeCost);
buttons.add(upgrade);
RedButton smith = new RedButton(Messages.get(this, "smith", 2000), 6){
@Override
protected void onClick() {
Blacksmith.Quest.favor -= 2000;
Blacksmith.Quest.smiths++;
WndBlacksmith.this.hide();
GameScene.show(new WndSmith(troll, hero));
}
};
smith.enable(Blacksmith.Quest.favor >= 2000);
buttons.add(smith);
RedButton cashOut = new RedButton(Messages.get(this, "cashout", Blacksmith.Quest.favor), 6){
@Override
protected void onClick() {
new Gold(Blacksmith.Quest.favor).doPickUp(Dungeon.hero, Dungeon.hero.pos);
Blacksmith.Quest.favor = 0;
WndBlacksmith.this.hide();
}
};
cashOut.enable(true);
buttons.add(cashOut);
float pos = message.bottom() + 3*GAP;
for (RedButton b : buttons){
@@ -92,4 +162,345 @@ public class WndBlacksmith extends Window {
}
//public so that it can be directly called for pre-v2.2.0 quest completions
public static class WndReforge extends Window {
private static final int WIDTH = 120;
private static final int BTN_SIZE = 32;
private static final float GAP = 2;
private static final float BTN_GAP = 5;
private ItemButton btnPressed;
private ItemButton btnItem1;
private ItemButton btnItem2;
private RedButton btnReforge;
public WndReforge( Blacksmith troll, Hero hero ) {
super();
IconTitle titlebar = new IconTitle();
titlebar.icon( troll.sprite() );
titlebar.label( Messages.titleCase( troll.name() ) );
titlebar.setRect( 0, 0, WIDTH, 0 );
add( titlebar );
RenderedTextBlock message = PixelScene.renderTextBlock( Messages.get(this, "message"), 6 );
message.maxWidth( WIDTH);
message.setPos(0, titlebar.bottom() + GAP);
add( message );
btnItem1 = new ItemButton() {
@Override
protected void onClick() {
btnPressed = btnItem1;
GameScene.selectItem( itemSelector );
}
};
btnItem1.setRect( (WIDTH - BTN_GAP) / 2 - BTN_SIZE, message.top() + message.height() + BTN_GAP, BTN_SIZE, BTN_SIZE );
add( btnItem1 );
btnItem2 = new ItemButton() {
@Override
protected void onClick() {
btnPressed = btnItem2;
GameScene.selectItem( itemSelector );
}
};
btnItem2.setRect( btnItem1.right() + BTN_GAP, btnItem1.top(), BTN_SIZE, BTN_SIZE );
add( btnItem2 );
btnReforge = new RedButton( Messages.get(this, "reforge") ) {
@Override
protected void onClick() {
Item first, second;
if (btnItem1.item().trueLevel() > btnItem2.item().trueLevel()) {
first = btnItem1.item();
second = btnItem2.item();
} else {
first = btnItem2.item();
second = btnItem1.item();
}
Sample.INSTANCE.play( Assets.Sounds.EVOKE );
ScrollOfUpgrade.upgrade( Dungeon.hero );
Item.evoke( Dungeon.hero );
if (second.isEquipped( Dungeon.hero )) {
((EquipableItem)second).doUnequip( Dungeon.hero, false );
}
second.detach( Dungeon.hero.belongings.backpack );
if (second instanceof Armor){
BrokenSeal seal = ((Armor) second).checkSeal();
if (seal != null){
Dungeon.level.drop( seal, Dungeon.hero.pos );
}
}
//preserves enchant/glyphs if present
if (first instanceof Weapon && ((Weapon) first).hasGoodEnchant()){
((Weapon) first).upgrade(true);
} else if (first instanceof Armor && ((Armor) first).hasGoodGlyph()){
((Armor) first).upgrade(true);
} else {
first.upgrade();
}
Badges.validateItemLevelAquired( first );
Item.updateQuickslot();
Blacksmith.Quest.favor -= 500 * (int)Math.pow(2, Blacksmith.Quest.reforges);
Blacksmith.Quest.reforges++;
hide();
}
};
btnReforge.enable( false );
btnReforge.setRect( 0, btnItem1.bottom() + BTN_GAP, WIDTH, 20 );
add( btnReforge );
resize( WIDTH, (int)btnReforge.bottom() );
}
protected WndBag.ItemSelector itemSelector = new WndBag.ItemSelector() {
@Override
public String textPrompt() {
return Messages.get(WndReforge.class, "prompt");
}
@Override
public Class<?extends Bag> preferredBag(){
return Belongings.Backpack.class;
}
@Override
public boolean itemSelectable(Item item) {
return item.isIdentified() && item.isUpgradable();
}
@Override
public void onSelect( Item item ) {
if (item != null && btnPressed.parent != null) {
btnPressed.item(item);
Item item1 = btnItem1.item();
Item item2 = btnItem2.item();
//need 2 items
if (item1 == null || item2 == null) {
btnReforge.enable(false);
//both of the same type
} else if (item1.getClass() != item2.getClass()) {
btnReforge.enable(false);
//and not the literal same item (unless quantity is >1)
} else if (item1 == item2 && item1.quantity() == 1) {
btnReforge.enable(false);
} else {
btnReforge.enable(true);
}
}
}
};
}
private class HardenSelector extends WndBag.ItemSelector {
@Override
public String textPrompt() {
return Messages.get(this, "prompt");
}
@Override
public Class<?extends Bag> preferredBag(){
return Belongings.Backpack.class;
}
@Override
public boolean itemSelectable(Item item) {
return item.isUpgradable()
&& item.isIdentified()
&& ((item instanceof MeleeWeapon && !((Weapon) item).enchantHardened)
|| (item instanceof Armor && !((Armor) item).glyphHardened));
}
@Override
public void onSelect(Item item) {
if (item != null) {
if (item instanceof Weapon){
((Weapon) item).enchantHardened = true;
} else if (item instanceof Armor){
((Armor) item).glyphHardened = true;
}
int hardenCost = Blacksmith.Quest.hardens == 0 ? 500 : 1000;
Blacksmith.Quest.favor -= hardenCost;
Blacksmith.Quest.hardens++;
WndBlacksmith.this.hide();
Sample.INSTANCE.play(Assets.Sounds.EVOKE);
Item.evoke( Dungeon.hero );
}
}
}
private class UpgradeSelector extends WndBag.ItemSelector {
@Override
public String textPrompt() {
return Messages.get(this, "prompt");
}
@Override
public Class<?extends Bag> preferredBag(){
return Belongings.Backpack.class;
}
@Override
public boolean itemSelectable(Item item) {
return item.isUpgradable()
&& item.isIdentified()
&& item.level() < 3;
}
@Override
public void onSelect(Item item) {
if (item != null) {
item.upgrade();
int upgradeCost = Blacksmith.Quest.upgrades == 0 ? 1000 : 1500;
Blacksmith.Quest.favor -= upgradeCost;
Blacksmith.Quest.upgrades++;
WndBlacksmith.this.hide();
Sample.INSTANCE.play(Assets.Sounds.EVOKE);
ScrollOfUpgrade.upgrade( Dungeon.hero );
Item.evoke( Dungeon.hero );
}
}
}
public static class WndSmith extends Window {
private static final int WIDTH = 120;
private static final int BTN_SIZE = 32;
private static final int BTN_GAP = 5;
private static final int GAP = 2;
Item[] rewards = new Item[3];
int rewardLevel;
public WndSmith( Blacksmith troll, Hero hero ){
super();
IconTitle titlebar = new IconTitle();
titlebar.icon(troll.sprite());
titlebar.label(Messages.titleCase(troll.name()));
RenderedTextBlock message = PixelScene.renderTextBlock( Messages.get(this, "prompt"), 6 );
titlebar.setRect( 0, 0, WIDTH, 0 );
add( titlebar );
message.maxWidth(WIDTH);
message.setPos(0, titlebar.bottom() + GAP);
add( message );
rewards[0] = Generator.randomWeapon(3, true);
do {
rewards[1] = Generator.randomWeapon(3, true);
} while (rewards[0].getClass() == rewards[1].getClass());
rewards[2] = Generator.randomArmor(3);
//15%:+0, 55%:+1, 20%:+2, 5%:+3
float itemLevelRoll = Random.Float();
if (itemLevelRoll < 0.2f){
rewardLevel = 0;
} else if (itemLevelRoll < 0.75f){
rewardLevel = 1;
} else if (itemLevelRoll < 0.95f){
rewardLevel = 2;
} else {
rewardLevel = 3;
}
int count = 0;
for (Item i : rewards){
count++;
i.level(rewardLevel);
if (i instanceof Weapon) {
((Weapon) i).enchant(null);
} else if (i instanceof Armor){
((Armor) i).inscribe(null);
}
i.cursed = false;
ItemButton btnReward = new ItemButton(){
@Override
protected void onClick() {
GameScene.show(new RewardWindow(troll, hero, item()));
}
};
btnReward.item( i );
btnReward.setRect( count*(WIDTH - BTN_GAP) / 3 - BTN_SIZE, message.top() + message.height() + BTN_GAP, BTN_SIZE, BTN_SIZE );
add( btnReward );
}
resize(WIDTH, (int)message.bottom() + 2*BTN_GAP + BTN_SIZE);
}
@Override
public void onBackPressed() {
//do nothing
}
private class RewardWindow extends WndInfoItem {
public RewardWindow( Blacksmith troll, Hero hero, Item item ) {
super(item);
RedButton btnConfirm = new RedButton(Messages.get(WndSadGhost.class, "confirm")){
@Override
protected void onClick() {
RewardWindow.this.hide();
item.identify(false);
Sample.INSTANCE.play(Assets.Sounds.EVOKE);
Item.evoke( Dungeon.hero );
if (item.doPickUp( Dungeon.hero )) {
GLog.i( Messages.capitalize(Messages.get(Dungeon.hero, "you_now_have", item.name())) );
} else {
Dungeon.level.drop( item, Dungeon.hero.pos ).sprite.drop();
}
WndSmith.this.hide();
}
};
btnConfirm.setRect(0, height+2, width/2-1, 16);
add(btnConfirm);
RedButton btnCancel = new RedButton(Messages.get(WndSadGhost.class, "cancel")){
@Override
protected void onClick() {
RewardWindow.this.hide();
}
};
btnCancel.setRect(btnConfirm.right()+2, height+2, btnConfirm.width(), 16);
add(btnCancel);
resize(width, (int)btnCancel.bottom());
}
}
}
}

View File

@@ -1,136 +0,0 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2023 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.windows;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.ui.ItemButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
//pre-v2.2.0
public class WndBlacksmithOld extends Window {
private static final int BTN_SIZE = 36;
private static final float GAP = 2;
private static final float BTN_GAP = 10;
private static final int WIDTH = 116;
private ItemButton btnPressed;
private ItemButton btnItem1;
private ItemButton btnItem2;
private RedButton btnReforge;
public WndBlacksmithOld(Blacksmith troll, Hero hero ) {
super();
IconTitle titlebar = new IconTitle();
titlebar.icon( troll.sprite() );
titlebar.label( Messages.titleCase( troll.name() ) );
titlebar.setRect( 0, 0, WIDTH, 0 );
add( titlebar );
RenderedTextBlock message = PixelScene.renderTextBlock( Messages.get(this, "prompt"), 6 );
message.maxWidth( WIDTH);
message.setPos(0, titlebar.bottom() + GAP);
add( message );
btnItem1 = new ItemButton() {
@Override
protected void onClick() {
btnPressed = btnItem1;
GameScene.selectItem( itemSelector );
}
};
btnItem1.setRect( (WIDTH - BTN_GAP) / 2 - BTN_SIZE, message.top() + message.height() + BTN_GAP, BTN_SIZE, BTN_SIZE );
add( btnItem1 );
btnItem2 = new ItemButton() {
@Override
protected void onClick() {
btnPressed = btnItem2;
GameScene.selectItem( itemSelector );
}
};
btnItem2.setRect( btnItem1.right() + BTN_GAP, btnItem1.top(), BTN_SIZE, BTN_SIZE );
add( btnItem2 );
btnReforge = new RedButton( Messages.get(this, "reforge") ) {
@Override
protected void onClick() {
Blacksmith.upgrade( btnItem1.item(), btnItem2.item() );
hide();
}
};
btnReforge.enable( false );
btnReforge.setRect( 0, btnItem1.bottom() + BTN_GAP, WIDTH, 20 );
add( btnReforge );
resize( WIDTH, (int)btnReforge.bottom() );
}
protected WndBag.ItemSelector itemSelector = new WndBag.ItemSelector() {
@Override
public String textPrompt() {
return Messages.get(WndBlacksmithOld.class, "select");
}
@Override
public Class<?extends Bag> preferredBag(){
return Belongings.Backpack.class;
}
@Override
public boolean itemSelectable(Item item) {
return item.isUpgradable();
}
@Override
public void onSelect( Item item ) {
if (item != null && btnPressed.parent != null) {
btnPressed.item( item );
if (btnItem1.item() != null && btnItem2.item() != null) {
String result = Blacksmith.verify( btnItem1.item(), btnItem2.item() );
if (result != null) {
GameScene.show( new WndMessage( result ) );
btnReforge.enable( false );
} else {
btnReforge.enable( true );
}
}
}
}
};
}