v3.2.0: reworked thrown weapons to work in 'sets':
- sets are upgraded/enchanted/etc. as a unit, default size of 3 - upgrading completely repairs a set - durability boost per upgrade down to 1.5x from 3x - Internal buff added to prevent upgrade repair duplication exploits - lots of effects that apply to melee weapons now apply to thrown: identification, enchants, curses, etc. - liquid metal recipe adjusted (liquid metal itself still needs changes) - Huntress ID talent changed now that thrown weapons are IDable - darts effectively unchanged, they all belong to the same set, still not upgradeable - no balance changes to accomodate this yet, tbd.
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.5 KiB |
@@ -1091,7 +1091,7 @@ actors.hero.talent.perfect_copy.desc=_+1:_ The shadow clone gains _10%_ of the h
|
|||||||
actors.hero.talent.natures_bounty.title=nature's bounty
|
actors.hero.talent.natures_bounty.title=nature's bounty
|
||||||
actors.hero.talent.natures_bounty.desc=_+1:_ The Huntress can find _4 berries_ hidden in tall grass as she explores the next few floors of the dungeon.\n\n_+2:_ The Huntress can find _6 berries_ hidden in tall grass as she explores the next few floors of the dungeon.\n\nBerries are eaten quickly, restore a small amount of satiety, and might contain a usable seed.
|
actors.hero.talent.natures_bounty.desc=_+1:_ The Huntress can find _4 berries_ hidden in tall grass as she explores the next few floors of the dungeon.\n\n_+2:_ The Huntress can find _6 berries_ hidden in tall grass as she explores the next few floors of the dungeon.\n\nBerries are eaten quickly, restore a small amount of satiety, and might contain a usable seed.
|
||||||
actors.hero.talent.survivalists_intuition.title=survivalist's intuition
|
actors.hero.talent.survivalists_intuition.title=survivalist's intuition
|
||||||
actors.hero.talent.survivalists_intuition.desc=_+1:_ The Huntress identifies all equipment _1.75x faster_.\n\n_+2:_ The Huntress identifies all equipment _2.5x faster_.
|
actors.hero.talent.survivalists_intuition.desc=_+1:_ The Huntress identifies thrown weapons _3x faster_.\n\n_+2:_ The Huntress identifies thrown weapons _when she attacks with them_.
|
||||||
actors.hero.talent.followup_strike.title=followup strike
|
actors.hero.talent.followup_strike.title=followup strike
|
||||||
actors.hero.talent.followup_strike.desc=_+1:_ When the Huntress hits an enemy with her bow or a thrown weapon, her next melee attack against that enemy deals _2 bonus damage_.\n\n_+2:_ When the Huntress hits an enemy with her bow or a thrown weapon, her next melee attack against that enemy deals _3 bonus damage_.
|
actors.hero.talent.followup_strike.desc=_+1:_ When the Huntress hits an enemy with her bow or a thrown weapon, her next melee attack against that enemy deals _2 bonus damage_.\n\n_+2:_ When the Huntress hits an enemy with her bow or a thrown weapon, her next melee attack against that enemy deals _3 bonus damage_.
|
||||||
actors.hero.talent.natures_aid.title=nature's aid
|
actors.hero.talent.natures_aid.title=nature's aid
|
||||||
|
|||||||
@@ -1163,7 +1163,7 @@ items.scrolls.scrollofupgrade.name=scroll of upgrade
|
|||||||
items.scrolls.scrollofupgrade.inv_title=Upgrade an item
|
items.scrolls.scrollofupgrade.inv_title=Upgrade an item
|
||||||
items.scrolls.scrollofupgrade.weaken_curse=The scroll of upgrade weakens the curse on your item.
|
items.scrolls.scrollofupgrade.weaken_curse=The scroll of upgrade weakens the curse on your item.
|
||||||
items.scrolls.scrollofupgrade.remove_curse=The scroll of upgrade cleanses the curse on your item!
|
items.scrolls.scrollofupgrade.remove_curse=The scroll of upgrade cleanses the curse on your item!
|
||||||
items.scrolls.scrollofupgrade.desc=This scroll will upgrade a single item. Wands will increase in power and number of charges, weapons and armor will deal and block more damage, and the effects of rings will intensify.\n\nIt can even weaken or sometimes totally dispel curses, though it is not as potent as a scroll of remove curse. Unfortunately, the upgrading magic can also erase enchantments or glyphs on higher level gear.
|
items.scrolls.scrollofupgrade.desc=This scroll will upgrade a single item or set of thrown weapons. Wands will increase in power and number of charges, weapons and armor will deal and block more damage, thrown weapon sets will be fully repaired and more durable, and the effects of rings will intensify.\n\nIt can even weaken or sometimes totally dispel curses, though it is not as potent as a scroll of remove curse. Unfortunately, the upgrading magic can also erase enchantments or glyphs on higher level gear.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -2105,7 +2105,7 @@ items.weapon.missiles.darts.dart.tip_two=tip 2 darts with 1 seed
|
|||||||
items.weapon.missiles.darts.dart.tip_one=tip 1 dart with 1 seed
|
items.weapon.missiles.darts.dart.tip_one=tip 1 dart with 1 seed
|
||||||
items.weapon.missiles.darts.dart.tip_cancel=cancel
|
items.weapon.missiles.darts.dart.tip_cancel=cancel
|
||||||
items.weapon.missiles.darts.dart.desc=These simple shafts of spike-tipped wood are weighted to fly true and sting their prey with a flick of the wrist. They can be tipped with seeds to gain bonus effects when thrown.
|
items.weapon.missiles.darts.dart.desc=These simple shafts of spike-tipped wood are weighted to fly true and sting their prey with a flick of the wrist. They can be tipped with seeds to gain bonus effects when thrown.
|
||||||
items.weapon.missiles.darts.dart.unlimited_uses=However, due to their simple construction darts will effectively last forever.
|
items.weapon.missiles.darts.dart.unlimited_uses=Due to their simple construction darts will effectively last forever.
|
||||||
|
|
||||||
items.weapon.missiles.darts.displacingdart.name=displacing dart
|
items.weapon.missiles.darts.displacingdart.name=displacing dart
|
||||||
items.weapon.missiles.darts.displacingdart.desc=These darts are tipped with a fadeleaf-based compound which will teleport their target a short distance away.
|
items.weapon.missiles.darts.displacingdart.desc=These darts are tipped with a fadeleaf-based compound which will teleport their target a short distance away.
|
||||||
@@ -2138,7 +2138,6 @@ items.weapon.missiles.darts.tippeddart.clean_desc=This action will remove the se
|
|||||||
items.weapon.missiles.darts.tippeddart.clean_all=clean all
|
items.weapon.missiles.darts.tippeddart.clean_all=clean all
|
||||||
items.weapon.missiles.darts.tippeddart.clean_one=clean one
|
items.weapon.missiles.darts.tippeddart.clean_one=clean one
|
||||||
items.weapon.missiles.darts.tippeddart.cancel=cancel
|
items.weapon.missiles.darts.tippeddart.cancel=cancel
|
||||||
items.weapon.missiles.darts.tippeddart.durability=Tipped darts will lose their tips and become regular darts when used.
|
|
||||||
items.weapon.missiles.darts.tippeddart.uses_left=This stack of darts has _%d/%d_ uses left before one tip wears off.
|
items.weapon.missiles.darts.tippeddart.uses_left=This stack of darts has _%d/%d_ uses left before one tip wears off.
|
||||||
items.weapon.missiles.darts.tippeddart.unlimited_uses=_But these are of such high quality that they will effectively last forever._
|
items.weapon.missiles.darts.tippeddart.unlimited_uses=_But these are of such high quality that they will effectively last forever._
|
||||||
items.weapon.missiles.darts.tippeddart.about_to_break=Your dart's tip is about to expire.
|
items.weapon.missiles.darts.tippeddart.about_to_break=Your dart's tip is about to expire.
|
||||||
@@ -2169,13 +2168,18 @@ items.weapon.missiles.javelin.desc=These larger throwing spears are weighted to
|
|||||||
items.weapon.missiles.kunai.name=kunai
|
items.weapon.missiles.kunai.name=kunai
|
||||||
items.weapon.missiles.kunai.desc=These small knives are very powerful in the hands of a skilled user. They are most effective against unaware enemies.
|
items.weapon.missiles.kunai.desc=These small knives are very powerful in the hands of a skilled user. They are most effective against unaware enemies.
|
||||||
|
|
||||||
items.weapon.missiles.missileweapon.stats=This _tier-%1$d_ thrown weapon deals _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly.
|
items.weapon.missiles.missileweapon.stats_known=This set of _tier-%1$d_ thrown weapons deals _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly.
|
||||||
items.weapon.missiles.missileweapon.distance=This weapon is designed to be used at a distance, it is more accurate against distant enemies, but also much less accurate at melee range.
|
items.weapon.missiles.missileweapon.stats_unknown=Typically this set of _tier-%1$d_ thrown weapons deals _%2$d-%3$d damage_ and requires _%4$d strength_ to use properly.
|
||||||
|
items.weapon.missiles.missileweapon.probably_too_heavy=Probably this weapon is too heavy for you.
|
||||||
|
items.weapon.missiles.missileweapon.distance=Thrown weapons are more accurate against distant enemies, but less accurate at melee range.
|
||||||
items.weapon.missiles.missileweapon.durability=Thrown weapons will wear out and break as they are used.
|
items.weapon.missiles.missileweapon.durability=Thrown weapons will wear out and break as they are used.
|
||||||
items.weapon.missiles.missileweapon.uses_left=This stack of weapons has _%d/%d_ uses left before one breaks.
|
items.weapon.missiles.missileweapon.uses_left=This set of thrown weapons has _%d/%d_ uses left before one breaks.
|
||||||
items.weapon.missiles.missileweapon.unlimited_uses=_But these are of such high quality that they will effectively last forever._
|
items.weapon.missiles.missileweapon.unlimited_uses=This set is of such high quality that it will effectively last forever.
|
||||||
|
items.weapon.missiles.missileweapon.unknown_uses=Typically this set of thrown weapons will have _%d_ uses before one breaks.
|
||||||
|
items.weapon.missiles.missileweapon.curse_discover=This thrown weapon is cursed!
|
||||||
items.weapon.missiles.missileweapon.about_to_break=Your thrown weapon is about to break.
|
items.weapon.missiles.missileweapon.about_to_break=Your thrown weapon is about to break.
|
||||||
items.weapon.missiles.missileweapon.has_broken=One of your thrown weapons has broken.
|
items.weapon.missiles.missileweapon.has_broken=One of your thrown weapons has broken.
|
||||||
|
items.weapon.missiles.missileweapon.dust=The thrown weapon crumbles to dust as you touch it.
|
||||||
items.weapon.missiles.missileweapon$placeholder.name=thrown weapon
|
items.weapon.missiles.missileweapon$placeholder.name=thrown weapon
|
||||||
|
|
||||||
items.weapon.missiles.shuriken.name=shuriken
|
items.weapon.missiles.shuriken.name=shuriken
|
||||||
@@ -2195,11 +2199,11 @@ items.weapon.missiles.throwingspear.name=throwing spear
|
|||||||
items.weapon.missiles.throwingspear.desc=These lightweight spears have thin frames which are clearly designed to be thrown, and not thrusted.
|
items.weapon.missiles.throwingspear.desc=These lightweight spears have thin frames which are clearly designed to be thrown, and not thrusted.
|
||||||
|
|
||||||
items.weapon.missiles.throwingspike.name=throwing spike
|
items.weapon.missiles.throwingspike.name=throwing spike
|
||||||
items.weapon.missiles.throwingspike.desc=These pointed shafts of metal are meant to be thrown into distant enemies. While they aren't very strong, their simple all-metal construction makes them reasonably durable.
|
items.weapon.missiles.throwingspike.desc=These durable pointed shafts of metal are meant to be thrown into distant enemies.
|
||||||
items.weapon.missiles.throwingspike.discover_hint=One of the heroes starts with this item.
|
items.weapon.missiles.throwingspike.discover_hint=One of the heroes starts with this item.
|
||||||
|
|
||||||
items.weapon.missiles.throwingstone.name=throwing stone
|
items.weapon.missiles.throwingstone.name=throwing stone
|
||||||
items.weapon.missiles.throwingstone.desc=These stones are sanded down to make them able to be thrown with more power than a regular stone. Despite the craftsmanship they still aren't a very reliable weapon, but at least they won't stick to enemies.
|
items.weapon.missiles.throwingstone.desc=These stones are sanded down to make them able to be thrown with more power than a regular stone.
|
||||||
items.weapon.missiles.throwingstone.discover_hint=One of the heroes starts with this item.
|
items.weapon.missiles.throwingstone.discover_hint=One of the heroes starts with this item.
|
||||||
|
|
||||||
items.weapon.missiles.tomahawk.name=tomahawk
|
items.weapon.missiles.tomahawk.name=tomahawk
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ journal.document.alchemy_guide.exotic_scrolls.body=Exotic scrolls can be made wi
|
|||||||
journal.document.alchemy_guide.bombs.title=Enhanced Bombs
|
journal.document.alchemy_guide.bombs.title=Enhanced Bombs
|
||||||
journal.document.alchemy_guide.bombs.body=A standard black powder bomb can be mixed with a specific item to create an enhanced bomb.
|
journal.document.alchemy_guide.bombs.body=A standard black powder bomb can be mixed with a specific item to create an enhanced bomb.
|
||||||
journal.document.alchemy_guide.weapons.title=Enhancing Weapons
|
journal.document.alchemy_guide.weapons.title=Enhancing Weapons
|
||||||
journal.document.alchemy_guide.weapons.body=Some of the lighter or more magical weapons can be used in alchemy!\n\nEach thrown weapon produces enough liquid metal to fully repair another weapon of the same level and tier.\n\nOne wand will produce enough arcane resin to upgrade two wands of the same level, but no higher than +3.
|
journal.document.alchemy_guide.weapons.body=Some of the lighter or more magical weapons can be used in alchemy!\n\nEach thrown weapon set produces enough liquid metal to fully repair another set of the same level and tier. Note that alchemizing a set will destroy the whole set, even if it isn't all present!\n\nOne wand will produce enough arcane resin to upgrade two wands of the same level, but no higher than +3.
|
||||||
journal.document.alchemy_guide.brews_elixirs.title=Brews and Elixirs
|
journal.document.alchemy_guide.brews_elixirs.title=Brews and Elixirs
|
||||||
journal.document.alchemy_guide.brews_elixirs.body=Brews and elixirs are advanced potions with a variety of effects, usually with a single use.
|
journal.document.alchemy_guide.brews_elixirs.body=Brews and elixirs are advanced potions with a variety of effects, usually with a single use.
|
||||||
journal.document.alchemy_guide.spells.title=Spells
|
journal.document.alchemy_guide.spells.title=Spells
|
||||||
|
|||||||
@@ -375,6 +375,7 @@ windows.wndupgrade.damage=Damage
|
|||||||
windows.wndupgrade.blocking=Blocking
|
windows.wndupgrade.blocking=Blocking
|
||||||
windows.wndupgrade.weight=Weight
|
windows.wndupgrade.weight=Weight
|
||||||
windows.wndupgrade.durability=Durability
|
windows.wndupgrade.durability=Durability
|
||||||
|
windows.wndupgrade.quantity=Quantity
|
||||||
windows.wndupgrade.zap_damage=Zap Damage
|
windows.wndupgrade.zap_damage=Zap Damage
|
||||||
windows.wndupgrade.corrosion_damage=Corrosion Damage
|
windows.wndupgrade.corrosion_damage=Corrosion Damage
|
||||||
windows.wndupgrade.ward_damage=Ward Damage
|
windows.wndupgrade.ward_damage=Ward Damage
|
||||||
|
|||||||
@@ -1067,7 +1067,8 @@ public class Hero extends Char {
|
|||||||
|| item instanceof TimekeepersHourglass.sandBag
|
|| item instanceof TimekeepersHourglass.sandBag
|
||||||
|| item instanceof DriedRose.Petal
|
|| item instanceof DriedRose.Petal
|
||||||
|| item instanceof Key
|
|| item instanceof Key
|
||||||
|| item instanceof Guidebook) {
|
|| item instanceof Guidebook
|
||||||
|
|| item.quantity() == 0) {
|
||||||
//Do Nothing
|
//Do Nothing
|
||||||
} else if (item instanceof DarkGold) {
|
} else if (item instanceof DarkGold) {
|
||||||
DarkGold existing = belongings.getItem(DarkGold.class);
|
DarkGold existing = belongings.getItem(DarkGold.class);
|
||||||
|
|||||||
@@ -690,6 +690,10 @@ public enum Talent {
|
|||||||
if (item instanceof Wand){
|
if (item instanceof Wand){
|
||||||
factor *= 1f + 2.0f*hero.pointsInTalent(SCHOLARS_INTUITION);
|
factor *= 1f + 2.0f*hero.pointsInTalent(SCHOLARS_INTUITION);
|
||||||
}
|
}
|
||||||
|
// 3x/instant speed with Huntress talent (see MissileWeapon.proc)
|
||||||
|
if (item instanceof MissileWeapon){
|
||||||
|
factor *= 1f + 2.0f*hero.pointsInTalent(SURVIVALISTS_INTUITION);
|
||||||
|
}
|
||||||
// 2x/instant for Rogue (see onItemEqupped), also id's type on equip/on pickup
|
// 2x/instant for Rogue (see onItemEqupped), also id's type on equip/on pickup
|
||||||
if (item instanceof Ring){
|
if (item instanceof Ring){
|
||||||
factor *= 1f + hero.pointsInTalent(THIEFS_INTUITION);
|
factor *= 1f + hero.pointsInTalent(THIEFS_INTUITION);
|
||||||
|
|||||||
+13
-15
@@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items;
|
|||||||
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
|
||||||
@@ -128,6 +129,10 @@ public class LiquidMetal extends Item {
|
|||||||
return item instanceof MissileWeapon && !(item instanceof Dart);
|
return item instanceof MissileWeapon && !(item instanceof Dart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO this needs to fix broken thrown weapons too
|
||||||
|
// should also only apply to IDed thrown weapons?
|
||||||
|
// TODO maybe thrown weps and wands can just be known uncursed in order to make recipe?
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSelect( Item item ) {
|
public void onSelect( Item item ) {
|
||||||
if (item != null && item instanceof MissileWeapon) {
|
if (item != null && item instanceof MissileWeapon) {
|
||||||
@@ -171,31 +176,24 @@ public class LiquidMetal extends Item {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean testIngredients(ArrayList<Item> ingredients) {
|
public boolean testIngredients(ArrayList<Item> ingredients) {
|
||||||
for (Item i : ingredients){
|
return ingredients.size() == 1
|
||||||
if (!(i instanceof MissileWeapon)){
|
&& ingredients.get(0) instanceof MissileWeapon
|
||||||
return false;
|
&& ingredients.get(0).isIdentified()
|
||||||
}
|
&& !ingredients.get(0).cursed;
|
||||||
}
|
|
||||||
|
|
||||||
return !ingredients.isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int cost(ArrayList<Item> ingredients) {
|
public int cost(ArrayList<Item> ingredients) {
|
||||||
int cost = 1;
|
return 3;
|
||||||
for (Item i : ingredients){
|
|
||||||
cost += i.quantity();
|
|
||||||
}
|
|
||||||
return cost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item brew(ArrayList<Item> ingredients) {
|
public Item brew(ArrayList<Item> ingredients) {
|
||||||
Item result = sampleOutput(ingredients);
|
Item result = sampleOutput(ingredients);
|
||||||
|
|
||||||
for (Item i : ingredients){
|
MissileWeapon w = (MissileWeapon) ingredients.get(0);
|
||||||
i.quantity(0);
|
w.quantity(0);
|
||||||
}
|
Buff.affect(Dungeon.hero, MissileWeapon.UpgradedSetTracker.class).levelThresholds.put(w.setID, Integer.MAX_VALUE);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ public abstract class Recipe {
|
|||||||
//*******
|
//*******
|
||||||
|
|
||||||
private static Recipe[] variableRecipes = new Recipe[]{
|
private static Recipe[] variableRecipes = new Recipe[]{
|
||||||
new LiquidMetal.Recipe()
|
//none for now
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Recipe[] oneIngredientRecipes = new Recipe[]{
|
private static Recipe[] oneIngredientRecipes = new Recipe[]{
|
||||||
@@ -176,6 +176,7 @@ public abstract class Recipe {
|
|||||||
new ExoticPotion.PotionToExotic(),
|
new ExoticPotion.PotionToExotic(),
|
||||||
new ExoticScroll.ScrollToExotic(),
|
new ExoticScroll.ScrollToExotic(),
|
||||||
new ArcaneResin.Recipe(),
|
new ArcaneResin.Recipe(),
|
||||||
|
new LiquidMetal.Recipe(),
|
||||||
new BlizzardBrew.Recipe(),
|
new BlizzardBrew.Recipe(),
|
||||||
new InfernalBrew.Recipe(),
|
new InfernalBrew.Recipe(),
|
||||||
new AquaBrew.Recipe(),
|
new AquaBrew.Recipe(),
|
||||||
@@ -254,9 +255,10 @@ public abstract class Recipe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean usableInRecipe(Item item){
|
public static boolean usableInRecipe(Item item){
|
||||||
|
//only upgradeable thrown weapons and wands allowed among equipment items
|
||||||
if (item instanceof EquipableItem){
|
if (item instanceof EquipableItem){
|
||||||
//only thrown weapons and wands allowed among equipment items
|
return item.isIdentified() && !item.cursed &&
|
||||||
return item.isIdentified() && !item.cursed && item instanceof MissileWeapon;
|
item instanceof MissileWeapon && item.isUpgradable();
|
||||||
} else if (item instanceof Wand) {
|
} else if (item instanceof Wand) {
|
||||||
return item.isIdentified() && !item.cursed;
|
return item.isIdentified() && !item.cursed;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-2
@@ -26,8 +26,8 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
@@ -76,7 +76,7 @@ public class PotionOfMastery extends ExoticPotion {
|
|||||||
@Override
|
@Override
|
||||||
public boolean itemSelectable(Item item) {
|
public boolean itemSelectable(Item item) {
|
||||||
return
|
return
|
||||||
(item instanceof MeleeWeapon && !((MeleeWeapon) item).masteryPotionBonus)
|
(item instanceof Weapon && !(item instanceof SpiritBow) && !((Weapon) item).masteryPotionBonus)
|
||||||
|| (item instanceof Armor && !((Armor) item).masteryPotionBonus);
|
|| (item instanceof Armor && !((Armor) item).masteryPotionBonus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
|
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Transmuting;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Transmuting;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
|
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
|
||||||
@@ -124,7 +125,11 @@ public class ScrollOfTransmutation extends InventoryScroll {
|
|||||||
}
|
}
|
||||||
Dungeon.hero.spend(-Dungeon.hero.cooldown()); //cancel equip/unequip time
|
Dungeon.hero.spend(-Dungeon.hero.cooldown()); //cancel equip/unequip time
|
||||||
} else {
|
} else {
|
||||||
item.detach(Dungeon.hero.belongings.backpack);
|
if (item instanceof MissileWeapon){
|
||||||
|
item.detachAll(Dungeon.hero.belongings.backpack);
|
||||||
|
} else {
|
||||||
|
item.detach(Dungeon.hero.belongings.backpack);
|
||||||
|
}
|
||||||
if (!result.collect()) {
|
if (!result.collect()) {
|
||||||
Dungeon.level.drop(result, curUser.pos).sprite.drop();
|
Dungeon.level.drop(result, curUser.pos).sprite.drop();
|
||||||
} else if (result.stackable && Dungeon.hero.belongings.getSimilar(result) != null){
|
} else if (result.stackable && Dungeon.hero.belongings.getSimilar(result) != null){
|
||||||
@@ -237,7 +242,7 @@ public class ScrollOfTransmutation extends InventoryScroll {
|
|||||||
} while (Challenges.isItemBlocked(n) || n.getClass() == w.getClass());
|
} while (Challenges.isItemBlocked(n) || n.getClass() == w.getClass());
|
||||||
|
|
||||||
n.level(0);
|
n.level(0);
|
||||||
n.quantity(1);
|
n.quantity(w.quantity());
|
||||||
int level = w.trueLevel();
|
int level = w.trueLevel();
|
||||||
if (level > 0) {
|
if (level > 0) {
|
||||||
n.upgrade( level );
|
n.upgrade( level );
|
||||||
@@ -253,6 +258,11 @@ public class ScrollOfTransmutation extends InventoryScroll {
|
|||||||
n.cursed = w.cursed;
|
n.cursed = w.cursed;
|
||||||
n.augment = w.augment;
|
n.augment = w.augment;
|
||||||
n.enchantHardened = w.enchantHardened;
|
n.enchantHardened = w.enchantHardened;
|
||||||
|
|
||||||
|
//technically a new set, ensure old one is destroyed (except for darts)
|
||||||
|
if (w instanceof MissileWeapon && w.isUpgradable()){
|
||||||
|
Buff.affect(Dungeon.hero, MissileWeapon.UpgradedSetTracker.class).levelThresholds.put(((MissileWeapon) w).setID, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -29,9 +29,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.InventoryScroll;
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.InventoryScroll;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
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.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
||||||
@@ -68,7 +66,7 @@ public class ScrollOfEnchantment extends ExoticScroll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean enchantable( Item item ){
|
public static boolean enchantable( Item item ){
|
||||||
return (item instanceof MeleeWeapon || item instanceof SpiritBow || item instanceof Armor);
|
return (item instanceof Weapon || item instanceof Armor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void confirmCancelation() {
|
private void confirmCancelation() {
|
||||||
|
|||||||
+2
-5
@@ -32,11 +32,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.quest.MetalShard;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfMight;
|
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfMight;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRemoveCurse;
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRemoveCurse;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
import com.watabou.noosa.audio.Sample;
|
import com.watabou.noosa.audio.Sample;
|
||||||
@@ -53,7 +50,7 @@ public class CurseInfusion extends InventorySpell {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean usableOnItem(Item item) {
|
protected boolean usableOnItem(Item item) {
|
||||||
return ((item instanceof EquipableItem && !(item instanceof MissileWeapon)) || item instanceof Wand);
|
return ((item instanceof EquipableItem && item.isUpgradable()) || item instanceof Wand);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -63,7 +60,7 @@ public class CurseInfusion extends InventorySpell {
|
|||||||
Sample.INSTANCE.play(Assets.Sounds.CURSED);
|
Sample.INSTANCE.play(Assets.Sounds.CURSED);
|
||||||
|
|
||||||
item.cursed = true;
|
item.cursed = true;
|
||||||
if (item instanceof MeleeWeapon || item instanceof SpiritBow) {
|
if (item instanceof Weapon) {
|
||||||
Weapon w = (Weapon) item;
|
Weapon w = (Weapon) item;
|
||||||
if (w.enchantment != null) {
|
if (w.enchantment != null) {
|
||||||
//if we are freshly applying curse infusion, don't replace an existing curse
|
//if we are freshly applying curse infusion, don't replace an existing curse
|
||||||
|
|||||||
+7
@@ -295,6 +295,13 @@ public class SpiritBow extends Weapon {
|
|||||||
image = ItemSpriteSheet.SPIRIT_ARROW;
|
image = ItemSpriteSheet.SPIRIT_ARROW;
|
||||||
|
|
||||||
hitSound = Assets.Sounds.HIT_ARROW;
|
hitSound = Assets.Sounds.HIT_ARROW;
|
||||||
|
|
||||||
|
setID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int defaultQuantity() {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+12
-8
@@ -67,6 +67,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Vampir
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.RunicBlade;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.RunicBlade;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Scimitar;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Scimitar;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
||||||
@@ -108,10 +109,12 @@ abstract public class Weapon extends KindOfWeapon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Augment augment = Augment.NONE;
|
public Augment augment = Augment.NONE;
|
||||||
|
|
||||||
private static final int USES_TO_ID = 20;
|
protected int usesToID(){
|
||||||
private float usesLeftToID = USES_TO_ID;
|
return 20;
|
||||||
private float availableUsesToID = USES_TO_ID/2f;
|
}
|
||||||
|
protected float usesLeftToID = usesToID();
|
||||||
|
protected float availableUsesToID = usesToID()/2f;
|
||||||
|
|
||||||
public Enchantment enchantment;
|
public Enchantment enchantment;
|
||||||
public boolean enchantHardened = false;
|
public boolean enchantHardened = false;
|
||||||
@@ -191,9 +194,10 @@ abstract public class Weapon extends KindOfWeapon {
|
|||||||
|
|
||||||
public void onHeroGainExp( float levelPercent, Hero hero ){
|
public void onHeroGainExp( float levelPercent, Hero hero ){
|
||||||
levelPercent *= Talent.itemIDSpeedFactor(hero, this);
|
levelPercent *= Talent.itemIDSpeedFactor(hero, this);
|
||||||
if (!levelKnown && isEquipped(hero) && availableUsesToID <= USES_TO_ID/2f) {
|
if (!levelKnown && (isEquipped(hero) || this instanceof MissileWeapon)
|
||||||
|
&& availableUsesToID <= usesToID()/2f) {
|
||||||
//gains enough uses to ID over 0.5 levels
|
//gains enough uses to ID over 0.5 levels
|
||||||
availableUsesToID = Math.min(USES_TO_ID/2f, availableUsesToID + levelPercent * USES_TO_ID);
|
availableUsesToID = Math.min(usesToID()/2f, availableUsesToID + levelPercent * usesToID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,8 +237,8 @@ abstract public class Weapon extends KindOfWeapon {
|
|||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
super.reset();
|
super.reset();
|
||||||
usesLeftToID = USES_TO_ID;
|
usesLeftToID = usesToID();
|
||||||
availableUsesToID = USES_TO_ID/2f;
|
availableUsesToID = usesToID()/2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+13
-2
@@ -28,13 +28,13 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SmokeParticle;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.bombs.Bomb;
|
import com.shatteredpixel.shatteredpixeldungeon.items.bombs.Bomb;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
import com.watabou.utils.PathFinder;
|
import com.watabou.utils.PathFinder;
|
||||||
import com.watabou.utils.Random;
|
|
||||||
|
|
||||||
public class Explosive extends Weapon.Enchantment {
|
public class Explosive extends Weapon.Enchantment {
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ public class Explosive extends Weapon.Enchantment {
|
|||||||
public int proc( Weapon weapon, Char attacker, Char defender, int damage ) {
|
public int proc( Weapon weapon, Char attacker, Char defender, int damage ) {
|
||||||
|
|
||||||
//average value of 5, or 20 hits to an explosion
|
//average value of 5, or 20 hits to an explosion
|
||||||
int durToReduce = Math.round(Random.IntRange(0, 10) * procChanceMultiplier(attacker));
|
int durToReduce = Math.round(24 * procChanceMultiplier(attacker));
|
||||||
int currentDurability = durability;
|
int currentDurability = durability;
|
||||||
durability -= durToReduce;
|
durability -= durToReduce;
|
||||||
|
|
||||||
@@ -82,9 +82,20 @@ public class Explosive extends Weapon.Enchantment {
|
|||||||
Item.updateQuickslot();
|
Item.updateQuickslot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (weapon instanceof MissileWeapon
|
||||||
|
&& ((MissileWeapon)weapon).parent != null && ((MissileWeapon) weapon).parent.enchantment instanceof Explosive){
|
||||||
|
((Explosive) ((MissileWeapon) weapon).parent.enchantment).durability = durability;
|
||||||
|
}
|
||||||
|
|
||||||
return damage;
|
return damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void merge(Explosive other){
|
||||||
|
if (other.durability < durability){
|
||||||
|
durability = other.durability;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean curse() {
|
public boolean curse() {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+259
-78
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles;
|
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
@@ -36,23 +37,29 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.MagicalHolster;
|
import com.shatteredpixel.shatteredpixeldungeon.items.bags.MagicalHolster;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfSharpshooting;
|
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfSharpshooting;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ParchmentScrap;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ShardOfOblivion;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.curses.Explosive;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Projecting;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Projecting;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.Dart;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.Dart;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
|
import com.watabou.noosa.audio.Sample;
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
import com.watabou.utils.Random;
|
import com.watabou.utils.Random;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
abstract public class MissileWeapon extends Weapon {
|
abstract public class MissileWeapon extends Weapon {
|
||||||
|
|
||||||
{
|
{
|
||||||
stackable = true;
|
stackable = true;
|
||||||
levelKnown = true;
|
quantity = defaultQuantity();
|
||||||
|
|
||||||
bones = true;
|
bones = true;
|
||||||
|
|
||||||
@@ -60,6 +67,9 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
usesTargeting = true;
|
usesTargeting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO maybe make this like actor IDs, instead of random? collisions unlikely, but it's messy
|
||||||
|
public long setID = new SecureRandom().nextLong();
|
||||||
|
|
||||||
//whether or not this instance of the item exists purely to trigger its effect. i.e. no dropping
|
//whether or not this instance of the item exists purely to trigger its effect. i.e. no dropping
|
||||||
public boolean spawnedForEffect = false;
|
public boolean spawnedForEffect = false;
|
||||||
|
|
||||||
@@ -72,9 +82,13 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
public boolean holster;
|
public boolean holster;
|
||||||
|
|
||||||
//used to reduce durability from the source weapon stack, rather than the one being thrown.
|
//used to reduce durability from the source weapon stack, rather than the one being thrown.
|
||||||
protected MissileWeapon parent;
|
public MissileWeapon parent;
|
||||||
|
|
||||||
public int tier;
|
public int tier;
|
||||||
|
|
||||||
|
protected int usesToID(){
|
||||||
|
return 10; //half of a melee weapon
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int min() {
|
public int min() {
|
||||||
@@ -107,7 +121,11 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int STRReq(int lvl){
|
public int STRReq(int lvl){
|
||||||
return STRReq(tier, lvl) - 1; //1 less str than normal for their tier
|
int req = STRReq(tier, lvl) - 1; //1 less str than normal for their tier
|
||||||
|
if (masteryPotionBonus){
|
||||||
|
req -= 2;
|
||||||
|
}
|
||||||
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
//use the parent item if this has been thrown from a parent
|
//use the parent item if this has been thrown from a parent
|
||||||
@@ -118,41 +136,24 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
return super.buffedLvl();
|
return super.buffedLvl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Item upgrade( boolean enchant ) {
|
||||||
|
if (!bundleRestoring) {
|
||||||
|
durability = MAX_DURABILITY;
|
||||||
|
quantity = fullSetQuantity = defaultQuantity();
|
||||||
|
Buff.affect(Dungeon.hero, UpgradedSetTracker.class).levelThresholds.put(setID, level()+1);
|
||||||
|
}
|
||||||
|
return super.upgrade( enchant );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
//FIXME some logic here assumes the items are in the player's inventory. Might need to adjust
|
|
||||||
public Item upgrade() {
|
public Item upgrade() {
|
||||||
if (!bundleRestoring) {
|
if (!bundleRestoring) {
|
||||||
durability = MAX_DURABILITY;
|
durability = MAX_DURABILITY;
|
||||||
if (quantity > 1) {
|
quantity = fullSetQuantity = defaultQuantity();
|
||||||
MissileWeapon upgraded = (MissileWeapon) split(1);
|
Buff.affect(Dungeon.hero, UpgradedSetTracker.class).levelThresholds.put(setID, level()+1);
|
||||||
upgraded.parent = null;
|
|
||||||
|
|
||||||
upgraded = (MissileWeapon) upgraded.upgrade();
|
|
||||||
|
|
||||||
//try to put the upgraded into inventory, if it didn't already merge
|
|
||||||
if (upgraded.quantity() == 1 && !upgraded.collect()) {
|
|
||||||
Dungeon.level.drop(upgraded, Dungeon.hero.pos);
|
|
||||||
}
|
|
||||||
updateQuickslot();
|
|
||||||
return upgraded;
|
|
||||||
} else {
|
|
||||||
super.upgrade();
|
|
||||||
|
|
||||||
Item similar = Dungeon.hero.belongings.getSimilar(this);
|
|
||||||
if (similar != null){
|
|
||||||
detach(Dungeon.hero.belongings.backpack);
|
|
||||||
Item result = similar.merge(this);
|
|
||||||
updateQuickslot();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
updateQuickslot();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return super.upgrade();
|
|
||||||
}
|
}
|
||||||
|
return super.upgrade();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -169,7 +170,7 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSimilar( Item item ) {
|
public boolean isSimilar( Item item ) {
|
||||||
return level() == item.level() && getClass() == item.getClass();
|
return trueLevel() == item.trueLevel() && getClass() == item.getClass() && setID == (((MissileWeapon) item).setID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -269,23 +270,82 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.proc(attacker, defender, damage);
|
if ((cursed || hasCurseEnchant()) && !cursedKnown){
|
||||||
|
GLog.n(Messages.get(this, "curse_discover"));
|
||||||
|
}
|
||||||
|
cursedKnown = true;
|
||||||
|
if (parent != null) parent.cursedKnown = true;
|
||||||
|
|
||||||
|
//instant ID with the right talent
|
||||||
|
if (attacker == Dungeon.hero && Dungeon.hero.pointsInTalent(Talent.SURVIVALISTS_INTUITION) == 2){
|
||||||
|
usesLeftToID = Math.min(usesLeftToID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = super.proc(attacker, defender, damage);
|
||||||
|
|
||||||
|
//handle ID progress over parent/child
|
||||||
|
if (parent != null && parent.usesLeftToID > usesLeftToID){
|
||||||
|
float diff = parent.usesLeftToID - usesLeftToID;
|
||||||
|
parent.usesLeftToID -= diff;
|
||||||
|
parent.availableUsesToID -= diff;
|
||||||
|
if (usesLeftToID <= 0) {
|
||||||
|
if (ShardOfOblivion.passiveIDDisabled()){
|
||||||
|
parent.setIDReady();
|
||||||
|
} else {
|
||||||
|
parent.identify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item virtual() {
|
||||||
|
Item item = super.virtual();
|
||||||
|
|
||||||
|
((MissileWeapon)item).setID = setID;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int defaultQuantity(){
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this is tracked to show warnings when upgrading and some of the set isn't present
|
||||||
|
public int fullSetQuantity = defaultQuantity();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item random() {
|
public Item random() {
|
||||||
if (!stackable) return this;
|
//+0: 75% (3/4)
|
||||||
|
//+1: 20% (4/20)
|
||||||
//2: 66.67% (2/3)
|
//+2: 5% (1/20)
|
||||||
//3: 26.67% (4/15)
|
int n = 0;
|
||||||
//4: 6.67% (1/15)
|
if (Random.Int(4) == 0) {
|
||||||
quantity = 2;
|
n++;
|
||||||
if (Random.Int(3) == 0) {
|
|
||||||
quantity++;
|
|
||||||
if (Random.Int(5) == 0) {
|
if (Random.Int(5) == 0) {
|
||||||
quantity++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
level(n);
|
||||||
|
|
||||||
|
//we use a separate RNG here so that variance due to things like parchment scrap
|
||||||
|
//does not affect levelgen
|
||||||
|
Random.pushGenerator(Random.Long());
|
||||||
|
|
||||||
|
//30% chance to be cursed
|
||||||
|
//10% chance to be enchanted
|
||||||
|
float effectRoll = Random.Float();
|
||||||
|
if (effectRoll < 0.3f * ParchmentScrap.curseChanceMultiplier()) {
|
||||||
|
enchant(Enchantment.randomCurse());
|
||||||
|
cursed = true;
|
||||||
|
} else if (effectRoll >= 1f - (0.1f * ParchmentScrap.enchantChanceMultiplier())){
|
||||||
|
enchant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Random.popGenerator();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,14 +387,16 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
durability += amount;
|
durability += amount;
|
||||||
durability = Math.min(durability, MAX_DURABILITY);
|
durability = Math.min(durability, MAX_DURABILITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float durabilityPerUse(){
|
public final float durabilityPerUse(){
|
||||||
//classes that override durabilityPerUse can turn rounding off, to do their own rounding after more logic
|
return durabilityPerUse(level());
|
||||||
return durabilityPerUse(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final float durabilityPerUse( boolean rounded){
|
//classes that add steps onto durabilityPerUse can turn rounding off, to do their own rounding after more logic
|
||||||
float usages = baseUses * (float)(Math.pow(3, level()));
|
protected boolean useRoundingInDurabilityCalc = true;
|
||||||
|
|
||||||
|
public float durabilityPerUse( int level ){
|
||||||
|
float usages = baseUses * (float)(Math.pow(1.5f, level));
|
||||||
|
|
||||||
//+50%/75% durability
|
//+50%/75% durability
|
||||||
if (Dungeon.hero != null && Dungeon.hero.hasTalent(Talent.DURABLE_PROJECTILES)){
|
if (Dungeon.hero != null && Dungeon.hero.hasTalent(Talent.DURABLE_PROJECTILES)){
|
||||||
@@ -349,7 +411,7 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
//at 100 uses, items just last forever.
|
//at 100 uses, items just last forever.
|
||||||
if (usages >= 100f) return 0;
|
if (usages >= 100f) return 0;
|
||||||
|
|
||||||
if (rounded){
|
if (useRoundingInDurabilityCalc){
|
||||||
usages = Math.round(usages);
|
usages = Math.round(usages);
|
||||||
//add a tiny amount to account for rounding error for calculations like 1/3
|
//add a tiny amount to account for rounding error for calculations like 1/3
|
||||||
return (MAX_DURABILITY/usages) + 0.001f;
|
return (MAX_DURABILITY/usages) + 0.001f;
|
||||||
@@ -366,6 +428,7 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
if (parent.durability <= parent.durabilityPerUse()){
|
if (parent.durability <= parent.durabilityPerUse()){
|
||||||
durability = 0;
|
durability = 0;
|
||||||
parent.durability = MAX_DURABILITY;
|
parent.durability = MAX_DURABILITY;
|
||||||
|
parent.fullSetQuantity--;
|
||||||
if (parent.durabilityPerUse() < 100f) {
|
if (parent.durabilityPerUse() < 100f) {
|
||||||
GLog.n(Messages.get(this, "has_broken"));
|
GLog.n(Messages.get(this, "has_broken"));
|
||||||
}
|
}
|
||||||
@@ -419,6 +482,34 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
quantity -= 1;
|
quantity -= 1;
|
||||||
durability += MAX_DURABILITY;
|
durability += MAX_DURABILITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
masteryPotionBonus = masteryPotionBonus || ((MissileWeapon) other).masteryPotionBonus;
|
||||||
|
levelKnown = levelKnown || other.levelKnown;
|
||||||
|
cursedKnown = cursedKnown || other.cursedKnown;
|
||||||
|
enchantHardened = enchantHardened || ((MissileWeapon) other).enchantHardened;
|
||||||
|
|
||||||
|
//if other has a curse/enchant status that's a higher priority, copy it. in the following order:
|
||||||
|
//curse infused
|
||||||
|
if (!curseInfusionBonus && ((MissileWeapon) other).curseInfusionBonus && ((MissileWeapon) other).hasCurseEnchant()){
|
||||||
|
enchantment = ((MissileWeapon) other).enchantment;
|
||||||
|
curseInfusionBonus = true;
|
||||||
|
cursed = cursed || other.cursed;
|
||||||
|
//enchanted
|
||||||
|
} else if (!curseInfusionBonus && !hasGoodEnchant() && ((MissileWeapon) other).hasGoodEnchant()){
|
||||||
|
enchantment = ((MissileWeapon) other).enchantment;
|
||||||
|
cursed = other.cursed;
|
||||||
|
//nothing
|
||||||
|
} else if (!curseInfusionBonus && hasCurseEnchant() && !((MissileWeapon) other).hasCurseEnchant()){
|
||||||
|
enchantment = ((MissileWeapon) other).enchantment;
|
||||||
|
cursed = other.cursed;
|
||||||
|
}
|
||||||
|
//cursed (no copy as other cannot have a higher priority status)
|
||||||
|
|
||||||
|
//special case for explosive, as it tracks a variable
|
||||||
|
if (((MissileWeapon) other).enchantment instanceof Explosive
|
||||||
|
&& enchantment instanceof Explosive){
|
||||||
|
((Explosive) enchantment).merge((Explosive) ((MissileWeapon) other).enchantment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -428,7 +519,7 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
bundleRestoring = true;
|
bundleRestoring = true;
|
||||||
Item split = super.split(amount);
|
Item split = super.split(amount);
|
||||||
bundleRestoring = false;
|
bundleRestoring = false;
|
||||||
|
|
||||||
//unless the thrown weapon will break, split off a max durability item and
|
//unless the thrown weapon will break, split off a max durability item and
|
||||||
//have it reduce the durability of the main stack. Cleaner to the player this way
|
//have it reduce the durability of the main stack. Cleaner to the player this way
|
||||||
if (split != null){
|
if (split != null){
|
||||||
@@ -443,59 +534,71 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
@Override
|
@Override
|
||||||
public boolean doPickUp(Hero hero, int pos) {
|
public boolean doPickUp(Hero hero, int pos) {
|
||||||
parent = null;
|
parent = null;
|
||||||
return super.doPickUp(hero, pos);
|
if (!UpgradedSetTracker.pickupValid(hero, this)){
|
||||||
|
Sample.INSTANCE.play( Assets.Sounds.ITEM );
|
||||||
|
hero.spendAndNext( TIME_TO_PICK_UP );
|
||||||
|
GLog.w(Messages.get(this, "dust"));
|
||||||
|
quantity(0);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return super.doPickUp(hero, pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isIdentified() {
|
public boolean isIdentified() {
|
||||||
return true;
|
return levelKnown && cursedKnown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String info() {
|
public String info() {
|
||||||
|
|
||||||
String info = super.info();
|
String info = super.info();
|
||||||
|
|
||||||
info += "\n\n" + Messages.get( MissileWeapon.class, "stats",
|
|
||||||
tier,
|
|
||||||
Math.round(augment.damageFactor(min())),
|
|
||||||
Math.round(augment.damageFactor(max())),
|
|
||||||
STRReq());
|
|
||||||
|
|
||||||
if (Dungeon.hero != null) {
|
if (levelKnown) {
|
||||||
if (STRReq() > Dungeon.hero.STR()) {
|
info += "\n\n" + Messages.get(MissileWeapon.class, "stats_known", tier, augment.damageFactor(min()), augment.damageFactor(max()), STRReq());
|
||||||
info += " " + Messages.get(Weapon.class, "too_heavy");
|
if (Dungeon.hero != null) {
|
||||||
} else if (Dungeon.hero.STR() > STRReq()) {
|
if (STRReq() > Dungeon.hero.STR()) {
|
||||||
info += " " + Messages.get(Weapon.class, "excess_str", Dungeon.hero.STR() - STRReq());
|
info += " " + Messages.get(Weapon.class, "too_heavy");
|
||||||
|
} else if (Dungeon.hero.STR() > STRReq()) {
|
||||||
|
info += " " + Messages.get(Weapon.class, "excess_str", Dungeon.hero.STR() - STRReq());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info += "\n\n" + Messages.get(MissileWeapon.class, "stats_unknown", tier, min(0), max(0), STRReq(0));
|
||||||
|
if (Dungeon.hero != null && STRReq(0) > Dungeon.hero.STR()) {
|
||||||
|
info += " " + Messages.get(MissileWeapon.class, "probably_too_heavy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enchantment != null && (cursedKnown || !enchantment.curse())){
|
if (enchantment != null && (cursedKnown || !enchantment.curse())){
|
||||||
info += "\n\n" + Messages.get(Weapon.class, "enchanted", enchantment.name());
|
info += "\n\n" + Messages.get(Weapon.class, "enchanted", enchantment.name());
|
||||||
|
if (enchantHardened) info += " " + Messages.get(Weapon.class, "enchant_hardened");
|
||||||
info += " " + Messages.get(enchantment, "desc");
|
info += " " + Messages.get(enchantment, "desc");
|
||||||
|
} else if (enchantHardened){
|
||||||
|
info += "\n\n" + Messages.get(Weapon.class, "hardened_no_enchant");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursed && isEquipped( Dungeon.hero )) {
|
if (cursedKnown && cursed) {
|
||||||
info += "\n\n" + Messages.get(Weapon.class, "cursed_worn");
|
|
||||||
} else if (cursedKnown && cursed) {
|
|
||||||
info += "\n\n" + Messages.get(Weapon.class, "cursed");
|
info += "\n\n" + Messages.get(Weapon.class, "cursed");
|
||||||
} else if (!isIdentified() && cursedKnown){
|
} else if (!isIdentified() && cursedKnown){
|
||||||
info += "\n\n" + Messages.get(Weapon.class, "not_cursed");
|
info += "\n\n" + Messages.get(Weapon.class, "not_cursed");
|
||||||
}
|
}
|
||||||
|
|
||||||
info += "\n\n" + Messages.get(MissileWeapon.class, "distance");
|
info += "\n\n" + Messages.get(MissileWeapon.class, "distance");
|
||||||
|
|
||||||
info += "\n\n" + Messages.get(this, "durability");
|
if (levelKnown) {
|
||||||
|
if (durabilityPerUse() > 0) {
|
||||||
if (durabilityPerUse() > 0){
|
info += "\n\n" + Messages.get(this, "uses_left",
|
||||||
info += " " + Messages.get(this, "uses_left",
|
(int) Math.ceil(durability / durabilityPerUse()),
|
||||||
(int)Math.ceil(durability/durabilityPerUse()),
|
(int) Math.ceil(MAX_DURABILITY / durabilityPerUse()));
|
||||||
(int)Math.ceil(MAX_DURABILITY/durabilityPerUse()));
|
} else {
|
||||||
} else {
|
info += "\n\n" + Messages.get(this, "unlimited_uses");
|
||||||
info += " " + Messages.get(this, "unlimited_uses");
|
}
|
||||||
|
} else {
|
||||||
|
info += "\n\n" + Messages.get(this, "unknown_uses", (int) Math.ceil(MAX_DURABILITY / durabilityPerUse(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,14 +607,19 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
return 6 * tier * quantity * (level() + 1);
|
return 6 * tier * quantity * (level() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String SET_ID = "set_id";
|
||||||
|
|
||||||
private static final String SPAWNED = "spawned";
|
private static final String SPAWNED = "spawned";
|
||||||
private static final String DURABILITY = "durability";
|
private static final String DURABILITY = "durability";
|
||||||
|
private static final String FULL_QUANTITY = "full_quantity";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeInBundle(Bundle bundle) {
|
public void storeInBundle(Bundle bundle) {
|
||||||
super.storeInBundle(bundle);
|
super.storeInBundle(bundle);
|
||||||
|
bundle.put(SET_ID, setID);
|
||||||
bundle.put(SPAWNED, spawnedForEffect);
|
bundle.put(SPAWNED, spawnedForEffect);
|
||||||
bundle.put(DURABILITY, durability);
|
bundle.put(DURABILITY, durability);
|
||||||
|
bundle.put(FULL_QUANTITY, fullSetQuantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean bundleRestoring = false;
|
private static boolean bundleRestoring = false;
|
||||||
@@ -521,8 +629,29 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
bundleRestoring = true;
|
bundleRestoring = true;
|
||||||
super.restoreFromBundle(bundle);
|
super.restoreFromBundle(bundle);
|
||||||
bundleRestoring = false;
|
bundleRestoring = false;
|
||||||
|
|
||||||
|
if (bundle.contains(SET_ID)){
|
||||||
|
setID = bundle.getLong(SET_ID);
|
||||||
|
//pre v3.2.0 logic
|
||||||
|
} else {
|
||||||
|
//if we have a higher than 0 level, assume that this was a solitary thrown wep upgrade
|
||||||
|
//turn it into a set of full quantity
|
||||||
|
if (level() > 0){
|
||||||
|
//set ID will be a random long
|
||||||
|
quantity = defaultQuantity();
|
||||||
|
fullSetQuantity = quantity;
|
||||||
|
|
||||||
|
//otherwise treat all currently spawned thrown weapons of the same class as if they are part of the same set
|
||||||
|
//darts already do this though and need no conversion
|
||||||
|
} else if (!(this instanceof Dart)){
|
||||||
|
levelKnown = cursedKnown = true;
|
||||||
|
setID = getClass().getSimpleName().hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spawnedForEffect = bundle.getBoolean(SPAWNED);
|
spawnedForEffect = bundle.getBoolean(SPAWNED);
|
||||||
durability = bundle.getFloat(DURABILITY);
|
durability = bundle.getFloat(DURABILITY);
|
||||||
|
fullSetQuantity = bundle.getInt(FULL_QUANTITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PlaceHolder extends MissileWeapon {
|
public static class PlaceHolder extends MissileWeapon {
|
||||||
@@ -533,7 +662,13 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSimilar(Item item) {
|
public boolean isSimilar(Item item) {
|
||||||
return item instanceof MissileWeapon;
|
//yes, even though it uses a dart outline
|
||||||
|
return item instanceof MissileWeapon && !(item instanceof Dart);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String status() {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -541,4 +676,50 @@ abstract public class MissileWeapon extends Weapon {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//also used by liquid metal crafting to track when a set is consumed
|
||||||
|
public static class UpgradedSetTracker extends Buff {
|
||||||
|
|
||||||
|
public HashMap<Long, Integer> levelThresholds = new HashMap<>();
|
||||||
|
|
||||||
|
public static boolean pickupValid(Hero h, MissileWeapon w){
|
||||||
|
if (h.buff(UpgradedSetTracker.class) != null){
|
||||||
|
HashMap<Long, Integer> levelThresholds = h.buff(UpgradedSetTracker.class).levelThresholds;
|
||||||
|
if (levelThresholds.containsKey(w.setID)){
|
||||||
|
return w.level() >= levelThresholds.get(w.setID);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String SET_IDD = "set_ids";
|
||||||
|
public static final String SET_LEVELS = "set_levels";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeInBundle(Bundle bundle) {
|
||||||
|
super.storeInBundle(bundle);
|
||||||
|
long[] IDs = new long[levelThresholds.size()];
|
||||||
|
int[] levels = new int[levelThresholds.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (Long ID : levelThresholds.keySet()){
|
||||||
|
IDs[i] = ID;
|
||||||
|
levels[i] = levelThresholds.get(ID);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
bundle.put(SET_IDD, IDs);
|
||||||
|
bundle.put(SET_LEVELS, levels);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreFromBundle(Bundle bundle) {
|
||||||
|
super.restoreFromBundle(bundle);
|
||||||
|
long[] IDs = bundle.getLongArray(SET_IDD);
|
||||||
|
int[] levels = bundle.getIntArray(SET_LEVELS);
|
||||||
|
levelThresholds.clear();
|
||||||
|
for (int i = 0; i <IDs.length; i++){
|
||||||
|
levelThresholds.put(IDs[i], levels[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-1
@@ -48,6 +48,8 @@ import java.util.ArrayList;
|
|||||||
public class Dart extends MissileWeapon {
|
public class Dart extends MissileWeapon {
|
||||||
|
|
||||||
{
|
{
|
||||||
|
levelKnown = true;
|
||||||
|
|
||||||
image = ItemSpriteSheet.DART;
|
image = ItemSpriteSheet.DART;
|
||||||
hitSound = Assets.Sounds.HIT_ARROW;
|
hitSound = Assets.Sounds.HIT_ARROW;
|
||||||
hitSoundPitch = 1.3f;
|
hitSoundPitch = 1.3f;
|
||||||
@@ -56,6 +58,9 @@ public class Dart extends MissileWeapon {
|
|||||||
|
|
||||||
//infinite, even with penalties
|
//infinite, even with penalties
|
||||||
baseUses = 1000;
|
baseUses = 1000;
|
||||||
|
|
||||||
|
//all darts share a set ID
|
||||||
|
setID = 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final String AC_TIP = "TIP";
|
protected static final String AC_TIP = "TIP";
|
||||||
@@ -242,7 +247,17 @@ public class Dart extends MissileWeapon {
|
|||||||
public boolean isUpgradable() {
|
public boolean isUpgradable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIdentified() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int defaultQuantity() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int value() {
|
public int value() {
|
||||||
return super.value()/2; //half normal value
|
return super.value()/2; //half normal value
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ public class RotDart extends TippedDart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float durabilityPerUse() {
|
public float durabilityPerUse(int level) {
|
||||||
return MAX_DURABILITY/5f; //always 5 uses
|
return MAX_DURABILITY/5f; //always 5 uses
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -163,9 +163,13 @@ public abstract class TippedDart extends Dart {
|
|||||||
|
|
||||||
private static int targetPos = -1;
|
private static int targetPos = -1;
|
||||||
|
|
||||||
|
{
|
||||||
|
useRoundingInDurabilityCalc = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float durabilityPerUse() {
|
public float durabilityPerUse(int level) {
|
||||||
float use = super.durabilityPerUse(false);
|
float use = super.durabilityPerUse(level);
|
||||||
|
|
||||||
if (Dungeon.hero != null) {
|
if (Dungeon.hero != null) {
|
||||||
use /= (1 + Dungeon.hero.pointsInTalent(Talent.DURABLE_TIPS));
|
use /= (1 + Dungeon.hero.pointsInTalent(Talent.DURABLE_TIPS));
|
||||||
|
|||||||
+4
-3
@@ -38,6 +38,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Recipe;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.AlchemistsToolkit;
|
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.AlchemistsToolkit;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrinketCatalyst;
|
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrinketCatalyst;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Document;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Document;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Journal;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Journal;
|
||||||
@@ -299,7 +300,7 @@ public class AlchemyScene extends PixelScene {
|
|||||||
if (item != null && inputs[0] != null) {
|
if (item != null && inputs[0] != null) {
|
||||||
for (int i = 0; i < inputs.length; i++) {
|
for (int i = 0; i < inputs.length; i++) {
|
||||||
if (inputs[i].item() == null) {
|
if (inputs[i].item() == null) {
|
||||||
if (item instanceof LiquidMetal){
|
if (item instanceof LiquidMetal || item instanceof MissileWeapon){
|
||||||
inputs[i].item(item.detachAll(Dungeon.hero.belongings.backpack));
|
inputs[i].item(item.detachAll(Dungeon.hero.belongings.backpack));
|
||||||
} else {
|
} else {
|
||||||
inputs[i].item(item.detach(Dungeon.hero.belongings.backpack));
|
inputs[i].item(item.detach(Dungeon.hero.belongings.backpack));
|
||||||
@@ -570,7 +571,7 @@ public class AlchemyScene extends PixelScene {
|
|||||||
if (item != null && inputs[0] != null) {
|
if (item != null && inputs[0] != null) {
|
||||||
for (int i = 0; i < inputs.length; i++) {
|
for (int i = 0; i < inputs.length; i++) {
|
||||||
if (inputs[i].item() == null) {
|
if (inputs[i].item() == null) {
|
||||||
if (item instanceof LiquidMetal){
|
if (item instanceof LiquidMetal || item instanceof MissileWeapon){
|
||||||
inputs[i].item(item.detachAll(Dungeon.hero.belongings.backpack));
|
inputs[i].item(item.detachAll(Dungeon.hero.belongings.backpack));
|
||||||
} else {
|
} else {
|
||||||
inputs[i].item(item.detach(Dungeon.hero.belongings.backpack));
|
inputs[i].item(item.detach(Dungeon.hero.belongings.backpack));
|
||||||
@@ -792,7 +793,7 @@ public class AlchemyScene extends PixelScene {
|
|||||||
ArrayList<Item> found = inventory.getAllSimilar(finding);
|
ArrayList<Item> found = inventory.getAllSimilar(finding);
|
||||||
while (!found.isEmpty() && needed > 0){
|
while (!found.isEmpty() && needed > 0){
|
||||||
Item detached;
|
Item detached;
|
||||||
if (finding instanceof LiquidMetal) {
|
if (finding instanceof LiquidMetal || finding instanceof MissileWeapon) {
|
||||||
detached = found.get(0).detachAll(inventory.backpack);
|
detached = found.get(0).detachAll(inventory.backpack);
|
||||||
} else {
|
} else {
|
||||||
detached = found.get(0).detach(inventory.backpack);
|
detached = found.get(0).detach(inventory.backpack);
|
||||||
|
|||||||
@@ -345,14 +345,6 @@ public class QuickRecipe extends Component {
|
|||||||
result.add(new QuickRecipe( new LiquidMetal.Recipe(),
|
result.add(new QuickRecipe( new LiquidMetal.Recipe(),
|
||||||
new ArrayList<Item>(Arrays.asList(new MissileWeapon.PlaceHolder())),
|
new ArrayList<Item>(Arrays.asList(new MissileWeapon.PlaceHolder())),
|
||||||
new LiquidMetal()));
|
new LiquidMetal()));
|
||||||
result.add(new QuickRecipe( new LiquidMetal.Recipe(),
|
|
||||||
new ArrayList<Item>(Arrays.asList(new MissileWeapon.PlaceHolder().quantity(2))),
|
|
||||||
new LiquidMetal()));
|
|
||||||
result.add(new QuickRecipe( new LiquidMetal.Recipe(),
|
|
||||||
new ArrayList<Item>(Arrays.asList(new MissileWeapon.PlaceHolder().quantity(3))),
|
|
||||||
new LiquidMetal()));
|
|
||||||
result.add(null);
|
|
||||||
result.add(null);
|
|
||||||
result.add(new QuickRecipe( new ArcaneResin.Recipe(),
|
result.add(new QuickRecipe( new ArcaneResin.Recipe(),
|
||||||
new ArrayList<Item>(Arrays.asList(new Wand.PlaceHolder())),
|
new ArrayList<Item>(Arrays.asList(new Wand.PlaceHolder())),
|
||||||
new ArcaneResin()));
|
new ArcaneResin()));
|
||||||
|
|||||||
+9
-5
@@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.windows;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
|
||||||
@@ -35,7 +36,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
|||||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Catalog;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
|
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
@@ -272,13 +273,16 @@ public class WndBlacksmith extends Window {
|
|||||||
if (second.isEquipped( Dungeon.hero )) {
|
if (second.isEquipped( Dungeon.hero )) {
|
||||||
((EquipableItem)second).doUnequip( Dungeon.hero, false );
|
((EquipableItem)second).doUnequip( Dungeon.hero, false );
|
||||||
}
|
}
|
||||||
second.detach( Dungeon.hero.belongings.backpack );
|
second.detachAll( Dungeon.hero.belongings.backpack );
|
||||||
|
|
||||||
if (second instanceof Armor){
|
if (second instanceof Armor){
|
||||||
BrokenSeal seal = ((Armor) second).checkSeal();
|
BrokenSeal seal = ((Armor) second).checkSeal();
|
||||||
if (seal != null){
|
if (seal != null){
|
||||||
Dungeon.level.drop( seal, Dungeon.hero.pos );
|
Dungeon.level.drop( seal, Dungeon.hero.pos );
|
||||||
}
|
}
|
||||||
|
} else if (second instanceof MissileWeapon){
|
||||||
|
Buff.affect(Dungeon.hero, MissileWeapon.UpgradedSetTracker.class)
|
||||||
|
.levelThresholds.put(((MissileWeapon) second).setID, Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//preserves enchant/glyphs if present
|
//preserves enchant/glyphs if present
|
||||||
@@ -346,8 +350,8 @@ public class WndBlacksmith extends Window {
|
|||||||
} else if (item1.getClass() != item2.getClass()) {
|
} else if (item1.getClass() != item2.getClass()) {
|
||||||
btnReforge.enable(false);
|
btnReforge.enable(false);
|
||||||
|
|
||||||
//and not the literal same item (unless quantity is >1)
|
//and not the literal same item
|
||||||
} else if (item1 == item2 && item1.quantity() == 1) {
|
} else if (item1 == item2) {
|
||||||
btnReforge.enable(false);
|
btnReforge.enable(false);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -375,7 +379,7 @@ public class WndBlacksmith extends Window {
|
|||||||
public boolean itemSelectable(Item item) {
|
public boolean itemSelectable(Item item) {
|
||||||
return item.isUpgradable()
|
return item.isUpgradable()
|
||||||
&& item.isIdentified() && !item.cursed
|
&& item.isIdentified() && !item.cursed
|
||||||
&& ((item instanceof MeleeWeapon && !((Weapon) item).enchantHardened)
|
&& ((item instanceof Weapon && !((Weapon) item).enchantHardened)
|
||||||
|| (item instanceof Armor && !((Armor) item).glyphHardened));
|
|| (item instanceof Armor && !((Armor) item).glyphHardened));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-2
@@ -245,12 +245,24 @@ public class WndUpgrade extends Window {
|
|||||||
//durability
|
//durability
|
||||||
if (toUpgrade instanceof MissileWeapon){
|
if (toUpgrade instanceof MissileWeapon){
|
||||||
//missile weapons are always IDed currently, so we always use true level
|
//missile weapons are always IDed currently, so we always use true level
|
||||||
int uses1 = (int)Math.ceil(100f/((MissileWeapon) toUpgrade).durabilityPerUse());
|
int uses1, uses2;
|
||||||
int uses2 = (int)Math.ceil(300f/((MissileWeapon) toUpgrade).durabilityPerUse());
|
if (toUpgrade.levelKnown) {
|
||||||
|
uses1 = (int) Math.ceil(100f / ((MissileWeapon) toUpgrade).durabilityPerUse(toUpgrade.level()));
|
||||||
|
uses2 = (int) Math.ceil(100f / ((MissileWeapon) toUpgrade).durabilityPerUse(toUpgrade.level()+1));
|
||||||
|
} else {
|
||||||
|
uses1 = (int) Math.ceil(100f / ((MissileWeapon) toUpgrade).durabilityPerUse(0));
|
||||||
|
uses2 = (int) Math.ceil(100f / ((MissileWeapon) toUpgrade).durabilityPerUse(1));
|
||||||
|
}
|
||||||
bottom = fillFields(Messages.get(this, "durability"),
|
bottom = fillFields(Messages.get(this, "durability"),
|
||||||
uses1 >= 100 ? "∞" : Integer.toString(uses1),
|
uses1 >= 100 ? "∞" : Integer.toString(uses1),
|
||||||
uses2 >= 100 ? "∞" : Integer.toString(uses2),
|
uses2 >= 100 ? "∞" : Integer.toString(uses2),
|
||||||
bottom);
|
bottom);
|
||||||
|
|
||||||
|
bottom = fillFields(Messages.get(this, "quantity"),
|
||||||
|
Integer.toString(toUpgrade.quantity()),
|
||||||
|
Integer.toString(((MissileWeapon) toUpgrade).defaultQuantity()),
|
||||||
|
bottom);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//we use a separate reference for wand properties so that mage's staff can include them
|
//we use a separate reference for wand properties so that mage's staff can include them
|
||||||
@@ -393,6 +405,10 @@ public class WndUpgrade extends Window {
|
|||||||
bottom = addMessage(Messages.get(this, "resin"), CharSprite.WARNING, bottom);
|
bottom = addMessage(Messages.get(this, "resin"), CharSprite.WARNING, bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (toUpgrade instanceof MissileWeapon && toUpgrade.quantity() < ((MissileWeapon) toUpgrade).fullSetQuantity){
|
||||||
|
bottom = addMessage("Weapons from this set that aren't in your inventory will crumble to dust.", CharSprite.WARNING, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
// *** Buttons for confirming/cancelling ***
|
// *** Buttons for confirming/cancelling ***
|
||||||
|
|
||||||
btnUpgrade = new RedButton(Messages.get(this, "upgrade")){
|
btnUpgrade = new RedButton(Messages.get(this, "upgrade")){
|
||||||
|
|||||||
Reference in New Issue
Block a user