diff --git a/core/src/main/assets/interfaces/badges.png b/core/src/main/assets/interfaces/badges.png index c3b02bf00..07433dc74 100644 Binary files a/core/src/main/assets/interfaces/badges.png and b/core/src/main/assets/interfaces/badges.png differ diff --git a/core/src/main/assets/interfaces/icons.png b/core/src/main/assets/interfaces/icons.png index 4b83ceee8..faa2047e2 100644 Binary files a/core/src/main/assets/interfaces/icons.png and b/core/src/main/assets/interfaces/icons.png differ diff --git a/core/src/main/assets/interfaces/talent_icons.png b/core/src/main/assets/interfaces/talent_icons.png index 031e5ef50..36e8e5580 100644 Binary files a/core/src/main/assets/interfaces/talent_icons.png and b/core/src/main/assets/interfaces/talent_icons.png differ diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index 005c864c4..adbd8ef05 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -502,6 +502,11 @@ actors.hero.heroclass.huntress_desc_short=The Huntress is a master of thrown wea actors.hero.heroclass.huntress_desc=The Huntress starts with a _unique spirit bow_, which can fire an infinite number of conjured arrows.\n\nThe Huntress can travel through tall grass _without trampling it_.\n\nThe Huntress also starts with _studded gloves_, cloth armor, a waterskin, and a velvet pouch.\n\nThe Huntress automatically identifies:\n_-_ Scrolls of Identify\n_-_ Potions of Mind Vision\n_-_ Scrolls of Lullaby actors.hero.heroclass.huntress_unlock=To unlock the Huntress _hit enemies with thrown weapons 10 times in one game._ +actors.hero.heroclass.duelist=Duelist +actors.hero.heroclass.duelist_desc_short=TODO +actors.hero.heroclass.duelist_desc=TODO +actors.hero.heroclass.duelist_unlock=To unlock the Duelist _equip a tier 2 or higher weapon with no strength penalty._ + actors.hero.herosubclass.berserker=berserker actors.hero.herosubclass.berserker_short_desc=The _Berserker_ builds rage as he takes damage. Rage increases his damage and can be activated at 100% for bonus shielding. actors.hero.herosubclass.berserker_desc=The Berserker gains rage as he takes physical damage, including damage that gets blocked by his armor! Rage steadily fades away over time, but fades more slowly if he is at low HP.\n\nThe Berserker deals up to +50% damage at 100% rage. At 100% rage he can also go berserk, gaining 2-6x his seal's maximum shielding depending on his missing health and keeping his rage at 100% as long as he has shielding left. However, the Berserker needs time to recover after he goes berserk. @@ -883,6 +888,7 @@ actors.mobs.npcs.wandmaker.intro_warrior=Oh, what a pleasant surprise to meet a actors.mobs.npcs.wandmaker.intro_rogue=Oh Goodness, you startled me! I haven't met a bandit from this place that still has his sanity, so you must be from the surface! If you're up to helping a stranger out, I may have a task for you. actors.mobs.npcs.wandmaker.intro_mage=Oh, hello %s! I heard there was some ruckus regarding you and the wizards institute? Oh never mind, I never liked those stick-in-the-muds anyway. If you're willing, I may have a task for you. actors.mobs.npcs.wandmaker.intro_huntress=Oh, hello miss! A friendly face is a pleasant surprise down here isn't it? In fact, I swear I've seen your face before, but I can't put my finger on it... Oh never mind, if you're here for adventure, I may have a task for you. +actors.mobs.npcs.wandmaker.intro_duelist=TODO, I have a task for you. actors.mobs.npcs.wandmaker.intro_1=\n\nI came here to find a rare ingredient for a wand, but I've gotten myself lost, and my magical shield is weakening. I'll need to leave soon, but can't bear to go without getting what I came for. actors.mobs.npcs.wandmaker.intro_dust=I'm looking for some _corpse dust._ It's a special kind of cursed bone meal that usually shows up in places like this. There should be a barricaded room around here somewhere, I'm sure some dust will turn up there. Do be careful though, the curse the dust carries is quite potent, _get back to me as fast as you can_ and I'll cleanse it for you. actors.mobs.npcs.wandmaker.intro_ember=I'm looking for some _fresh embers_ from a newborn fire elemental. Elementals usually pop up when a summoning ritual isn't controlled, so just find some candles and a ritual site and I'm sure you can get one to pop up. You might want to _keep some sort of freezing item handy_ though, elementals are very powerful, but ice will take them down quite easily. diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index 8a51214f1..3febb897e 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -109,6 +109,9 @@ items.armor.classarmor.transfer_complete=Your heroic armor's properties have bee items.armor.clotharmor.name=cloth armor items.armor.clotharmor.desc=This lightweight armor offers basic protection. +items.armor.duelistarmor.name=TODO +items.armor.duelistarmor.desc=TODO + items.armor.huntressarmor.name=hero's cloak items.armor.huntressarmor.no_enemies=No enemies in sight items.armor.huntressarmor.desc=While wearing this cloak, the Huntress can perform a special ability. @@ -1570,6 +1573,10 @@ items.weapon.melee.quarterstaff.name=quarterstaff items.weapon.melee.quarterstaff.stats_desc=This weapon blocks 0-2 damage. items.weapon.melee.quarterstaff.desc=A staff of hardwood, its ends are shod with iron. +items.weapon.melee.rapier.name=rapier +items.weapon.melee.rapier.stats_desc=This weapon blocks 0-1 damage. +items.weapon.melee.rapier.desc=TODO + items.weapon.melee.roundshield.name=round shield items.weapon.melee.roundshield.typical_stats_desc=Typically this weapon blocks 0-%d damage. This blocking scales with upgrades. items.weapon.melee.roundshield.stats_desc=This weapon blocks 0-%d damage. This blocking scales with upgrades. diff --git a/core/src/main/assets/messages/misc/misc.properties b/core/src/main/assets/messages/misc/misc.properties index 8523a4825..9825d04bd 100644 --- a/core/src/main/assets/messages/misc/misc.properties +++ b/core/src/main/assets/messages/misc/misc.properties @@ -176,6 +176,8 @@ badges$badge.unlock_rogue.title=Rogue Unlocked! badges$badge.unlock_rogue.desc=Unlock the Rogue by performing 10 surprise attacks in one game badges$badge.unlock_huntress.title=Huntress Unlocked! badges$badge.unlock_huntress.desc=Unlock the Huntress by hitting enemies with thrown weapons 10 times in one game +badges$badge.unlock_duelist.title=Duelist Unlocked! +badges$badge.unlock_duelist.desc=Unlock the Duelist by equipping a tier 2 or higher weapon with no strength penalty challenges.no_food=On diet challenges.no_food_desc=Food's already scarce, but you have to watch your portions as well!\n\n- Food and the horn of plenty are one third as effective at satisfying hunger\n- Other sources of satiety are unaffected diff --git a/core/src/main/assets/splashes/duelist.jpg b/core/src/main/assets/splashes/duelist.jpg new file mode 100644 index 000000000..dd7bbdd07 Binary files /dev/null and b/core/src/main/assets/splashes/duelist.jpg differ diff --git a/core/src/main/assets/sprites/duelist.png b/core/src/main/assets/sprites/duelist.png new file mode 100644 index 000000000..fc33764f1 Binary files /dev/null and b/core/src/main/assets/sprites/duelist.png differ diff --git a/core/src/main/assets/sprites/items.png b/core/src/main/assets/sprites/items.png index 7a0c05951..effe9d6be 100644 Binary files a/core/src/main/assets/sprites/items.png and b/core/src/main/assets/sprites/items.png differ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java index 19cc8b457..5d56c488f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java @@ -227,6 +227,7 @@ public class Assets { public static final String MAGE = "splashes/mage.jpg"; public static final String ROGUE = "splashes/rogue.jpg"; public static final String HUNTRESS = "splashes/huntress.jpg"; + public static final String DUELIST = "splashes/duelist.jpg"; } public static class Sprites { @@ -237,6 +238,7 @@ public class Assets { public static final String MAGE = "sprites/mage.png"; public static final String ROGUE = "sprites/rogue.png"; public static final String HUNTRESS = "sprites/huntress.png"; + public static final String DUELIST = "sprites/duelist.png"; public static final String AVATARS = "sprites/avatars.png"; public static final String PET = "sprites/pet.png"; public static final String AMULET = "sprites/amulet.png"; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Badges.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Badges.java index bcdf10c76..cf2e3f8dd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Badges.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Badges.java @@ -29,6 +29,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.bags.MagicalHolster; import com.shatteredpixel.shatteredpixeldungeon.items.bags.PotionBandolier; import com.shatteredpixel.shatteredpixeldungeon.items.bags.ScrollHolder; import com.shatteredpixel.shatteredpixeldungeon.items.bags.VelvetPouch; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon; import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; @@ -53,29 +54,32 @@ public class Badges { MASTERY_MAGE, MASTERY_ROGUE, MASTERY_HUNTRESS, + MASTERY_DUELIST, FOUND_RATMOGRIFY, //bronze UNLOCK_MAGE ( 1 ), UNLOCK_ROGUE ( 2 ), UNLOCK_HUNTRESS ( 3 ), - MONSTERS_SLAIN_1 ( 4 ), - MONSTERS_SLAIN_2 ( 5 ), - GOLD_COLLECTED_1 ( 6 ), - GOLD_COLLECTED_2 ( 7 ), - ITEM_LEVEL_1 ( 8 ), - LEVEL_REACHED_1 ( 9 ), - STRENGTH_ATTAINED_1 ( 10 ), - FOOD_EATEN_1 ( 11 ), - ITEMS_CRAFTED_1 ( 12 ), - BOSS_SLAIN_1 ( 13 ), - DEATH_FROM_FIRE ( 14 ), - DEATH_FROM_POISON ( 15 ), - DEATH_FROM_GAS ( 16 ), - DEATH_FROM_HUNGER ( 17 ), - DEATH_FROM_FALLING ( 18 ), - GAMES_PLAYED_1 ( 19, true ), - HIGH_SCORE_1 ( 20 ), + UNLOCK_DUELIST ( 4 ), + //UNLOCK_CLERIC ( 5 ), + MONSTERS_SLAIN_1 ( 6 ), + MONSTERS_SLAIN_2 ( 7 ), + GOLD_COLLECTED_1 ( 8 ), + GOLD_COLLECTED_2 ( 9 ), + ITEM_LEVEL_1 ( 10 ), + LEVEL_REACHED_1 ( 11 ), + STRENGTH_ATTAINED_1 ( 12 ), + FOOD_EATEN_1 ( 13 ), + ITEMS_CRAFTED_1 ( 14 ), + BOSS_SLAIN_1 ( 15 ), + DEATH_FROM_FIRE ( 16 ), + DEATH_FROM_POISON ( 17 ), + DEATH_FROM_GAS ( 18 ), + DEATH_FROM_HUNGER ( 19 ), + DEATH_FROM_FALLING ( 20 ), + GAMES_PLAYED_1 ( 21, true ), + HIGH_SCORE_1 ( 22 ), //silver NO_MONSTERS_SLAIN ( 32 ), @@ -104,6 +108,7 @@ public class Badges { BOSS_SLAIN_1_MAGE, BOSS_SLAIN_1_ROGUE, BOSS_SLAIN_1_HUNTRESS, + BOSS_SLAIN_1_DUELIST, BOSS_SLAIN_1_ALL_CLASSES ( 54, true ), GAMES_PLAYED_2 ( 55, true ), HIGH_SCORE_2 ( 56 ), @@ -149,6 +154,7 @@ public class Badges { VICTORY_MAGE, VICTORY_ROGUE, VICTORY_HUNTRESS, + VICTORY_DUELIST, VICTORY_ALL_CLASSES ( 103, true ), DEATH_FROM_ALL ( 104, true ), BOSS_SLAIN_3_GLADIATOR, @@ -699,6 +705,7 @@ public class Badges { firstBossClassBadges.put(HeroClass.MAGE, Badge.BOSS_SLAIN_1_MAGE); firstBossClassBadges.put(HeroClass.ROGUE, Badge.BOSS_SLAIN_1_ROGUE); firstBossClassBadges.put(HeroClass.HUNTRESS, Badge.BOSS_SLAIN_1_HUNTRESS); + firstBossClassBadges.put(HeroClass.DUELIST, Badge.BOSS_SLAIN_1_DUELIST); } private static LinkedHashMap victoryClassBadges = new LinkedHashMap<>(); @@ -707,6 +714,7 @@ public class Badges { victoryClassBadges.put(HeroClass.MAGE, Badge.VICTORY_MAGE); victoryClassBadges.put(HeroClass.ROGUE, Badge.VICTORY_ROGUE); victoryClassBadges.put(HeroClass.HUNTRESS, Badge.VICTORY_HUNTRESS); + victoryClassBadges.put(HeroClass.DUELIST, Badge.VICTORY_DUELIST); } private static LinkedHashMap thirdBossSubclassBadges = new LinkedHashMap<>(); @@ -816,18 +824,21 @@ public class Badges { Badge badge = null; switch (Dungeon.hero.heroClass) { - case WARRIOR: - badge = Badge.MASTERY_WARRIOR; - break; - case MAGE: - badge = Badge.MASTERY_MAGE; - break; - case ROGUE: - badge = Badge.MASTERY_ROGUE; - break; - case HUNTRESS: - badge = Badge.MASTERY_HUNTRESS; - break; + case WARRIOR: + badge = Badge.MASTERY_WARRIOR; + break; + case MAGE: + badge = Badge.MASTERY_MAGE; + break; + case ROGUE: + badge = Badge.MASTERY_ROGUE; + break; + case HUNTRESS: + badge = Badge.MASTERY_HUNTRESS; + break; + case DUELIST: + badge = Badge.MASTERY_DUELIST; + break; } unlock(badge); @@ -854,6 +865,14 @@ public class Badges { displayBadge( Badge.UNLOCK_HUNTRESS ); } } + + public static void validateDuelistUnlock(){ + if (Dungeon.hero.belongings.weapon instanceof MeleeWeapon + && ((MeleeWeapon) Dungeon.hero.belongings.weapon).tier >= 2 + && ((MeleeWeapon) Dungeon.hero.belongings.weapon).STRReq() <= Dungeon.hero.STR()){ + displayBadge( Badge.UNLOCK_DUELIST ); + } + } public static void validateMasteryCombo( int n ) { if (!local.contains( Badge.MASTERY_COMBO ) && n == 10) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java index 77613b64f..192144e74 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java @@ -51,9 +51,11 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfInvisibility; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfLiquidFlame; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfMindVision; +import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfIdentify; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfLullaby; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMagicMapping; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMirrorImage; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRage; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile; @@ -61,6 +63,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dagger; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gloves; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Rapier; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.WornShortsword; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingKnife; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingStone; @@ -72,7 +75,8 @@ public enum HeroClass { WARRIOR( HeroSubClass.BERSERKER, HeroSubClass.GLADIATOR ), MAGE( HeroSubClass.BATTLEMAGE, HeroSubClass.WARLOCK ), ROGUE( HeroSubClass.ASSASSIN, HeroSubClass.FREERUNNER ), - HUNTRESS( HeroSubClass.SNIPER, HeroSubClass.WARDEN ); + HUNTRESS( HeroSubClass.SNIPER, HeroSubClass.WARDEN ), + DUELIST( ); private HeroSubClass[] subClasses; @@ -115,6 +119,10 @@ public enum HeroClass { case HUNTRESS: initHuntress( hero ); break; + + case DUELIST: + initDuelist( hero ); + break; } if (SPDSettings.quickslotWaterskin()) { @@ -138,6 +146,8 @@ public enum HeroClass { return Badges.Badge.MASTERY_ROGUE; case HUNTRESS: return Badges.Badge.MASTERY_HUNTRESS; + case DUELIST: + return Badges.Badge.MASTERY_DUELIST; } return null; } @@ -199,6 +209,17 @@ public enum HeroClass { new ScrollOfLullaby().identify(); } + private static void initDuelist( Hero hero ) { + + (hero.belongings.weapon = new Rapier()).identify(); + + //quickslot and thrown weapons? + //Dungeon.quickslot.setSlot(0, hero.belongings.weapon); + + new PotionOfStrength().identify(); + new ScrollOfMirrorImage().identify(); + } + public String title() { return Messages.get(HeroClass.class, name()); } @@ -225,6 +246,8 @@ public enum HeroClass { return new ArmorAbility[]{new SmokeBomb(), new DeathMark(), new ShadowClone()}; case HUNTRESS: return new ArmorAbility[]{new SpectralBlades(), new NaturesPower(), new SpiritHawk()}; + case DUELIST: + return new ArmorAbility[]{}; } } @@ -238,6 +261,8 @@ public enum HeroClass { return Assets.Sprites.ROGUE; case HUNTRESS: return Assets.Sprites.HUNTRESS; + case DUELIST: + return Assets.Sprites.DUELIST; } } @@ -251,6 +276,8 @@ public enum HeroClass { return Assets.Splashes.ROGUE; case HUNTRESS: return Assets.Splashes.HUNTRESS; + case DUELIST: + return Assets.Splashes.DUELIST; } } @@ -267,6 +294,8 @@ public enum HeroClass { return Badges.isUnlocked(Badges.Badge.UNLOCK_ROGUE); case HUNTRESS: return Badges.isUnlocked(Badges.Badge.UNLOCK_HUNTRESS); + case DUELIST: + return Badges.isUnlocked(Badges.Badge.UNLOCK_DUELIST); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java index 187b06e1d..44316e031 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Talent.java @@ -144,10 +144,27 @@ public enum Talent { //Spirit Hawk T4 EAGLE_EYE(119, 4), GO_FOR_THE_EYES(120, 4), SWIFT_SPIRIT(121, 4), + //Duelist T1 + DUELIST_T1_1(128), DUELIST_T1_2(129), DUELIST_T1_3(130), DUELIST_T1_4(131), + //Duelist T2 + DUELIST_T2_1(132), DUELIST_T2_2(133), DUELIST_T2_3(134), DUELIST_T2_4(135), DUELIST_T2_5(136), + //Duelist T3 + DUELIST_T3_1(137, 3), DUELIST_T3_2(138, 3), + //Duelist S1 T3 + DUELIST_S1_1(139, 3), DUELIST_S1_2(140, 3), DUELIST_S1_3(141, 3), + //Duelist S2 T3 + DUELIST_S2_1(142, 3), DUELIST_S2_2(143, 3), DUELIST_S2_3(144, 3), + //Duelist A1 T4 + DUELIST_A1_1(145, 4), DUELIST_A1_2(146, 4), DUELIST_A1_3(147, 4), + //Duelist A2 T4 + DUELIST_A2_1(148, 4), DUELIST_A2_2(149, 4), DUELIST_A2_3(150, 4), + //Duelist A3 T4 + DUELIST_A3_1(151, 4), DUELIST_A3_2(152, 4), DUELIST_A3_3(153, 4), + //universal T4 HEROIC_ENERGY(26, 4), //See icon() and title() for special logic for this one //Ratmogrify T4 - RATSISTANCE(124, 4), RATLOMACY(125, 4), RATFORCEMENTS(126, 4); + RATSISTANCE(215, 4), RATLOMACY(216, 4), RATFORCEMENTS(217, 4); public static class ImprovisedProjectileCooldown extends FlavourBuff{ public int icon() { return BuffIndicator.TIME; } @@ -227,7 +244,7 @@ public enum Talent { public int icon(){ if (this == HEROIC_ENERGY){ if (Ratmogrify.useRatroicEnergy){ - return 127; + return 218; } HeroClass cls = Dungeon.hero != null ? Dungeon.hero.heroClass : GamesInProgress.selectedClass; switch (cls){ @@ -239,6 +256,8 @@ public enum Talent { return 90; case HUNTRESS: return 122; + case DUELIST: + return 154; } } else { return icon; @@ -557,6 +576,9 @@ public enum Talent { case HUNTRESS: Collections.addAll(tierTalents, NATURES_BOUNTY, SURVIVALISTS_INTUITION, FOLLOWUP_STRIKE, NATURES_AID); break; + case DUELIST: + Collections.addAll(tierTalents, DUELIST_T1_1, DUELIST_T1_2, DUELIST_T1_3, DUELIST_T1_4); + break; } for (Talent talent : tierTalents){ if (replacements.containsKey(talent)){ @@ -580,6 +602,9 @@ public enum Talent { case HUNTRESS: Collections.addAll(tierTalents, INVIGORATING_MEAL, RESTORED_NATURE, REJUVENATING_STEPS, HEIGHTENED_SENSES, DURABLE_PROJECTILES); break; + case DUELIST: + Collections.addAll(tierTalents, DUELIST_T2_1, DUELIST_T2_2, DUELIST_T2_3, DUELIST_T2_4, DUELIST_T2_5); + break; } for (Talent talent : tierTalents){ if (replacements.containsKey(talent)){ @@ -603,6 +628,9 @@ public enum Talent { case HUNTRESS: Collections.addAll(tierTalents, POINT_BLANK, SEER_SHOT); break; + case DUELIST: + Collections.addAll(tierTalents, DUELIST_T3_1, DUELIST_T3_2); + break; } for (Talent talent : tierTalents){ if (replacements.containsKey(talent)){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Wandmaker.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Wandmaker.java index 740aa90b0..49a77fdd0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Wandmaker.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/npcs/Wandmaker.java @@ -159,6 +159,9 @@ public class Wandmaker extends NPC { case HUNTRESS: msg1 += Messages.get(this, "intro_huntress"); break; + case DUELIST: + msg1 += Messages.get(this, "intro_duelist"); + break; } msg1 += Messages.get(this, "intro_1"); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java index 33e0f2239..927ae2494 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClothArmor; +import com.shatteredpixel.shatteredpixeldungeon.items.armor.DuelistArmor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.HuntressArmor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.LeatherArmor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.MageArmor; @@ -133,6 +134,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Mace; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Quarterstaff; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Rapier; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.RoundShield; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.RunicBlade; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Sai; @@ -344,9 +346,10 @@ public class Generator { WornShortsword.class, MagesStaff.class, Dagger.class, - Gloves.class + Gloves.class, + Rapier.class }; - WEP_T1.probs = new float[]{ 1, 0, 1, 1 }; + WEP_T1.probs = new float[]{ 1, 0, 1, 1, 1 }; WEP_T2.classes = new Class[]{ Shortsword.class, @@ -397,8 +400,10 @@ public class Generator { WarriorArmor.class, MageArmor.class, RogueArmor.class, - HuntressArmor.class}; - ARMOR.probs = new float[]{ 1, 1, 1, 1, 1, 0, 0, 0, 0 }; + HuntressArmor.class, + DuelistArmor.class + }; + ARMOR.probs = new float[]{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; //see Generator.randomMissile MISSILE.classes = new Class[]{}; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/KindOfWeapon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/KindOfWeapon.java index 00790ca6d..2c1d033ac 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/KindOfWeapon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/KindOfWeapon.java @@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; @@ -57,6 +58,7 @@ abstract public class KindOfWeapon extends EquipableItem { hero.belongings.weapon = this; activate( hero ); Talent.onItemEquipped(hero, this); + Badges.validateDuelistUnlock(); ActionIndicator.updateIcon(); updateQuickslot(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/ClassArmor.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/ClassArmor.java index 12dc89d9e..20fdf9d0c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/ClassArmor.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/ClassArmor.java @@ -99,22 +99,25 @@ abstract public class ClassArmor extends Armor { ClassArmor classArmor = null; switch (owner.heroClass) { - case WARRIOR: - classArmor = new WarriorArmor(); - BrokenSeal seal = armor.checkSeal(); - if (seal != null) { - classArmor.affixSeal(seal); - } - break; - case ROGUE: - classArmor = new RogueArmor(); - break; - case MAGE: - classArmor = new MageArmor(); - break; - case HUNTRESS: - classArmor = new HuntressArmor(); - break; + case WARRIOR: + classArmor = new WarriorArmor(); + BrokenSeal seal = armor.checkSeal(); + if (seal != null) { + classArmor.affixSeal(seal); + } + break; + case ROGUE: + classArmor = new RogueArmor(); + break; + case MAGE: + classArmor = new MageArmor(); + break; + case HUNTRESS: + classArmor = new HuntressArmor(); + break; + case DUELIST: + classArmor = new DuelistArmor(); + break; } classArmor.level(armor.trueLevel()); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/DuelistArmor.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/DuelistArmor.java new file mode 100644 index 000000000..f22065dc4 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/DuelistArmor.java @@ -0,0 +1,32 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2022 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.armor; + +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; + +public class DuelistArmor extends ClassArmor { + + { + image = ItemSpriteSheet.ARMOR_DUELIST; + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/HuntressArmor.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/HuntressArmor.java index 97ed30f49..87f57c5b4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/HuntressArmor.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/HuntressArmor.java @@ -25,7 +25,6 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; public class HuntressArmor extends ClassArmor { - { image = ItemSpriteSheet.ARMOR_HUNTRESS; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/MageArmor.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/MageArmor.java index 05e243f4c..d3210aa65 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/MageArmor.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/MageArmor.java @@ -24,7 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.armor; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; public class MageArmor extends ClassArmor { - + { image = ItemSpriteSheet.ARMOR_MAGE; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/RogueArmor.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/RogueArmor.java index 7608cea5c..d842946cb 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/RogueArmor.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/RogueArmor.java @@ -24,7 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.armor; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; public class RogueArmor extends ClassArmor { - + { image = ItemSpriteSheet.ARMOR_ROGUE; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Rapier.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Rapier.java new file mode 100644 index 000000000..ed418e680 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Rapier.java @@ -0,0 +1,53 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2022 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; + +public class Rapier extends MeleeWeapon { + + { + image = ItemSpriteSheet.RAPIER; + hitSound = Assets.Sounds.HIT_SLASH; + hitSoundPitch = 1.3f; + + tier = 1; + + bones = false; + } + + //might want to think on this more, it doesn't really make sense for duelist to get defense and warrior to have raw dmg + + @Override + public int max(int lvl) { + return 4*(tier+1) + //8 base, down from 10 + lvl*(tier+1); //scaling unchanged + } + + @Override + public int defenseFactor( Char owner ) { + return 1; //1 extra defence + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java index 2b4a80a89..61c15109a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/HeroSelectScene.java @@ -235,7 +235,7 @@ public class HeroSelectScene extends PixelScene { btnHeight += 6; } - int cols = 2; + int cols = (int)Math.ceil(heroBtns.size()/2f); float curX = (leftArea - btnWidth * cols + (cols-1))/2f; float curY = title.bottom() + uiSpacing; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java index 7b47d4780..306db33ad 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java @@ -203,6 +203,7 @@ public class ItemSpriteSheet { static{ assignItemRect(WORN_SHORTSWORD, 13, 13); assignItemRect(GLOVES, 12, 16); + assignItemRect(RAPIER, 13, 14); assignItemRect(DAGGER, 12, 13); assignItemRect(MAGES_STAFF, 15, 16); } @@ -346,6 +347,7 @@ public class ItemSpriteSheet { public static final int ARMOR_MAGE = ARMOR+6; public static final int ARMOR_ROGUE = ARMOR+7; public static final int ARMOR_HUNTRESS = ARMOR+8; + public static final int ARMOR_DUELIST = ARMOR+9; static{ assignItemRect(ARMOR_CLOTH, 15, 12); assignItemRect(ARMOR_LEATHER, 14, 13); @@ -356,6 +358,7 @@ public class ItemSpriteSheet { assignItemRect(ARMOR_MAGE, 15, 15); assignItemRect(ARMOR_ROGUE, 14, 12); assignItemRect(ARMOR_HUNTRESS, 13, 15); + assignItemRect(ARMOR_DUELIST, 12, 12); } //16 free slots diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java index 9fe54d1f4..dabafbbcd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java @@ -46,6 +46,7 @@ public enum Icons { MAGE, ROGUE, HUNTRESS, + DUELIST, //grey icons, mainly used for buttons, spacing for 16x16 EXIT, @@ -166,6 +167,9 @@ public enum Icons { case HUNTRESS: icon.frame( icon.texture.uvRectBySize( 64, 16, 16, 16 ) ); break; + case DUELIST: + icon.frame( icon.texture.uvRectBySize( 80, 16, 13, 14 ) ); + break; case EXIT: icon.frame( icon.texture.uvRectBySize( 0, 32, 15, 11 ) ); @@ -390,16 +394,18 @@ public enum Icons { public static Image get( HeroClass cl ) { switch (cl) { - case WARRIOR: - return get( WARRIOR ); - case MAGE: - return get( MAGE ); - case ROGUE: - return get( ROGUE ); - case HUNTRESS: - return get( HUNTRESS ); - default: - return null; + case WARRIOR: + return get( Icons.WARRIOR ); + case MAGE: + return get( Icons.MAGE ); + case ROGUE: + return get( Icons.ROGUE ); + case HUNTRESS: + return get( Icons.HUNTRESS ); + case DUELIST: + return get( Icons.DUELIST ); + default: + return null; } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java index 38bcf2fdc..569a6436b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java @@ -70,6 +70,9 @@ public class WndHeroInfo extends WndTabbed { case HUNTRESS: tabIcon = new ItemSprite(ItemSpriteSheet.SPIRIT_BOW, null); break; + case DUELIST: + tabIcon = new ItemSprite(ItemSpriteSheet.RAPIER, null); + break; } int finalHeight = MIN_HEIGHT; @@ -189,6 +192,11 @@ public class WndHeroInfo extends WndTabbed { new ItemSprite(ItemSpriteSheet.GLOVES), new ItemSprite(ItemSpriteSheet.SCROLL_ISAZ)}; break; + case DUELIST: + icons = new Image[]{ new ItemSprite(ItemSpriteSheet.RAPIER), + new ItemSprite(ItemSpriteSheet.RAPIER), + new ItemSprite(ItemSpriteSheet.SCROLL_ISAZ)}; + break; } for (Image im : icons) { add(im);