v1.2.0: reworked master thieves' armband
This commit is contained in:
parent
2bcacbaa5d
commit
1f45564487
|
@ -348,9 +348,20 @@ items.artifacts.lloydsbeacon.desc=Lloyd's beacon is an intricate magical device
|
|||
items.artifacts.lloydsbeacon.desc_set=This beacon was set somewhere on the level %d of Pixel Dungeon.
|
||||
|
||||
items.artifacts.masterthievesarmband.name=master thieves' armband
|
||||
items.artifacts.masterthievesarmband.ac_steal=STEAL
|
||||
items.artifacts.masterthievesarmband.no_charge=Your armband does not have enough charge.
|
||||
items.artifacts.masterthievesarmband.cursed=You can't use a cursed armband.
|
||||
items.artifacts.masterthievesarmband.full=Your armband is fully charged!
|
||||
items.artifacts.masterthievesarmband.prompt=Choose an enemy to target
|
||||
items.artifacts.masterthievesarmband.no_target=You must target an enemy that is adjacent to you
|
||||
items.artifacts.masterthievesarmband.steal_shopkeeper=You can't steal from shopkeepers directly.
|
||||
items.artifacts.masterthievesarmband.no_steal=That enemy has nothing to steal.
|
||||
items.artifacts.masterthievesarmband.stole_item=You stole an item: %s.
|
||||
items.artifacts.masterthievesarmband.failed_steal=You didn't manage to steal anything.
|
||||
items.artifacts.masterthievesarmband.level_up=Your armband grows stronger!
|
||||
items.artifacts.masterthievesarmband.desc=This purple velvet armband bears the mark of a master thief. This doesn't belong to you, but it probably didn't belong to its last user either.
|
||||
items.artifacts.masterthievesarmband.desc_cursed=The cursed armband is bound to your wrist, and somehow your pouch of gold seems to be slowly getting lighter...
|
||||
items.artifacts.masterthievesarmband.desc_worn=With the armband around your wrist, every piece of gold you find makes you desire other people's property more. Perhaps it wouldn't be too hard to steal from a shop...
|
||||
items.artifacts.masterthievesarmband.desc_worn=You feel power building in the armband on your wrist as you gain experience. You can use this power to steal from shops, or to rob enemies!\n\nRobbing enemies happens instantly, briefly disorients them, and gives you a chance to get whatever loot they have! This power is more effective against unaware enemies. Robbing the same enemy multiple times does not give more chances at loot.
|
||||
|
||||
items.artifacts.sandalsofnature.name=sandals of nature
|
||||
items.artifacts.sandalsofnature.name_1=shoes of nature
|
||||
|
|
|
@ -237,7 +237,7 @@ windows.wndsupportprompt.intro=Hello, I hope you're enjoying Shattered Pixel Dun
|
|||
windows.wndsupportprompt.close=Close
|
||||
|
||||
windows.wndtradeitem.buy=Buy for %dg
|
||||
windows.wndtradeitem.steal=Steal with %d%% chance
|
||||
windows.wndtradeitem.steal=Steal with %1$d%% chance\nCharges used: %2$d
|
||||
windows.wndtradeitem.sell=Sell for %dg
|
||||
windows.wndtradeitem.sell_1=Sell 1 for %dg
|
||||
windows.wndtradeitem.sell_all=Sell all for %dg
|
||||
|
|
|
@ -81,6 +81,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CloakOfShadows;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.EtherealChains;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HornOfPlenty;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.MasterThievesArmband;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.MagicalHolster;
|
||||
|
@ -1521,6 +1522,9 @@ public class Hero extends Char {
|
|||
AlchemistsToolkit.kitEnergy kit = buff(AlchemistsToolkit.kitEnergy.class);
|
||||
if (kit != null) kit.gainCharge(percent);
|
||||
|
||||
MasterThievesArmband.Thievery armband = buff(MasterThievesArmband.Thievery.class);
|
||||
if (armband != null) armband.gainCharge(percent);
|
||||
|
||||
Berserk berserk = buff(Berserk.class);
|
||||
if (berserk != null) berserk.recover(percent);
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ public class Acidic extends Scorpio {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
return new PotionOfExperience();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ public class ArmoredBrute extends Brute {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot () {
|
||||
public Item createLoot() {
|
||||
if (Random.Int( 4 ) == 0) {
|
||||
return new PlateArmor().random();
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public class Bat extends Mob {
|
|||
flying = true;
|
||||
|
||||
loot = new PotionOfHealing();
|
||||
lootChance = 0.1667f; //by default, see rollToDropLoot()
|
||||
lootChance = 0.1667f; //by default, see lootChance()
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,13 +76,12 @@ public class Bat extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
lootChance *= ((7f - Dungeon.LimitedDrops.BAT_HP.count) / 7f);
|
||||
super.rollToDropLoot();
|
||||
public float lootChance(){
|
||||
return super.lootChance() * ((7f - Dungeon.LimitedDrops.BAT_HP.count) / 7f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot(){
|
||||
public Item createLoot(){
|
||||
Dungeon.LimitedDrops.BAT_HP.count++;
|
||||
return super.createLoot();
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class DM200 extends Mob {
|
|||
maxLvl = 17;
|
||||
|
||||
loot = Random.oneOf(Generator.Category.WEAPON, Generator.Category.ARMOR);
|
||||
lootChance = 0.125f; //initially, see rollToDropLoot
|
||||
lootChance = 0.125f; //initially, see lootChance()
|
||||
|
||||
properties.add(Property.INORGANIC);
|
||||
properties.add(Property.LARGE);
|
||||
|
@ -69,14 +69,13 @@ public class DM200 extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
public float lootChance(){
|
||||
//each drop makes future drops 1/2 as likely
|
||||
// so loot chance looks like: 1/8, 1/16, 1/32, 1/64, etc.
|
||||
lootChance *= Math.pow(1/2f, Dungeon.LimitedDrops.DM200_EQUIP.count);
|
||||
super.rollToDropLoot();
|
||||
return super.lootChance() * (float)Math.pow(1/2f, Dungeon.LimitedDrops.DM200_EQUIP.count);
|
||||
}
|
||||
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Dungeon.LimitedDrops.DM200_EQUIP.count++;
|
||||
//uses probability tables for dwarf city
|
||||
if (loot == Generator.Category.WEAPON){
|
||||
|
|
|
@ -202,7 +202,7 @@ public class Eye extends Mob {
|
|||
|
||||
//generates an average of 1 dew, 0.25 seeds, and 0.25 stones
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Item loot;
|
||||
switch(Random.Int(4)){
|
||||
case 0: case 1: default:
|
||||
|
|
|
@ -111,7 +111,7 @@ public class GnollTrickster extends Gnoll {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
MissileWeapon drop = (MissileWeapon)super.createLoot();
|
||||
//half quantity, rounded up
|
||||
drop.quantity((drop.quantity()+1)/2);
|
||||
|
|
|
@ -47,7 +47,7 @@ public class Golem extends Mob {
|
|||
maxLvl = 22;
|
||||
|
||||
loot = Random.oneOf(Generator.Category.WEAPON, Generator.Category.ARMOR);
|
||||
lootChance = 0.125f; //initially, see rollToDropLoot
|
||||
lootChance = 0.125f; //initially, see lootChance()
|
||||
|
||||
properties.add(Property.INORGANIC);
|
||||
properties.add(Property.LARGE);
|
||||
|
@ -72,16 +72,19 @@ public class Golem extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
Imp.Quest.process( this );
|
||||
|
||||
public float lootChance() {
|
||||
//each drop makes future drops 1/2 as likely
|
||||
// so loot chance looks like: 1/8, 1/16, 1/32, 1/64, etc.
|
||||
lootChance *= Math.pow(1/2f, Dungeon.LimitedDrops.GOLEM_EQUIP.count);
|
||||
return super.lootChance() * (float)Math.pow(1/2f, Dungeon.LimitedDrops.GOLEM_EQUIP.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
Imp.Quest.process( this );
|
||||
super.rollToDropLoot();
|
||||
}
|
||||
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Dungeon.LimitedDrops.GOLEM_EQUIP.count++;
|
||||
//uses probability tables for demon halls
|
||||
if (loot == Generator.Category.WEAPON){
|
||||
|
|
|
@ -54,7 +54,7 @@ public class Guard extends Mob {
|
|||
maxLvl = 14;
|
||||
|
||||
loot = Generator.Category.ARMOR;
|
||||
lootChance = 0.2f; //by default, see rollToDropLoot()
|
||||
lootChance = 0.2f; //by default, see lootChance()
|
||||
|
||||
properties.add(Property.UNDEAD);
|
||||
|
||||
|
@ -137,15 +137,14 @@ public class Guard extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
public float lootChance() {
|
||||
//each drop makes future drops 1/2 as likely
|
||||
// so loot chance looks like: 1/5, 1/10, 1/20, 1/40, etc.
|
||||
lootChance *= Math.pow(1/2f, Dungeon.LimitedDrops.GUARD_ARM.count);
|
||||
super.rollToDropLoot();
|
||||
return super.lootChance() * (float)Math.pow(1/2f, Dungeon.LimitedDrops.GUARD_ARM.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Dungeon.LimitedDrops.GUARD_ARM.count++;
|
||||
return super.createLoot();
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle
|
|||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.MasterThievesArmband;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth;
|
||||
|
@ -631,10 +631,14 @@ public abstract class Mob extends Char {
|
|||
return damage;
|
||||
}
|
||||
|
||||
public boolean surprisedBy( Char enemy ){
|
||||
public final boolean surprisedBy( Char enemy ){
|
||||
return surprisedBy( enemy, true);
|
||||
}
|
||||
|
||||
public boolean surprisedBy( Char enemy, boolean attacking ){
|
||||
return enemy == Dungeon.hero
|
||||
&& (enemy.invisible > 0 || !enemySeen)
|
||||
&& ((Hero)enemy).canSurpriseAttack();
|
||||
&& (!attacking || ((Hero)enemy).canSurpriseAttack());
|
||||
}
|
||||
|
||||
public void aggro( Char ch ) {
|
||||
|
@ -726,18 +730,26 @@ public abstract class Mob extends Char {
|
|||
}
|
||||
}
|
||||
|
||||
public float lootChance(){
|
||||
float lootChance = this.lootChance;
|
||||
|
||||
lootChance *= RingOfWealth.dropChanceMultiplier( Dungeon.hero );
|
||||
|
||||
return lootChance;
|
||||
}
|
||||
|
||||
public void rollToDropLoot(){
|
||||
if (Dungeon.hero.lvl > maxLvl + 2) return;
|
||||
|
||||
float lootChance = this.lootChance;
|
||||
lootChance *= RingOfWealth.dropChanceMultiplier( Dungeon.hero );
|
||||
|
||||
if (Random.Float() < lootChance) {
|
||||
MasterThievesArmband.StolenTracker stolen = buff(MasterThievesArmband.StolenTracker.class);
|
||||
if (stolen == null || !stolen.itemWasStolen()) {
|
||||
if (Random.Float() < lootChance()) {
|
||||
Item loot = createLoot();
|
||||
if (loot != null) {
|
||||
Dungeon.level.drop(loot, pos).sprite.drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ring of wealth logic
|
||||
if (Ring.getBuffedBonus(Dungeon.hero, RingOfWealth.Wealth.class) > 0) {
|
||||
|
@ -777,7 +789,7 @@ public abstract class Mob extends Char {
|
|||
protected float lootChance = 0;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Item item;
|
||||
if (loot instanceof Generator.Category) {
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Adrenaline;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AllyBuff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ChampionEnemy;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
|
@ -54,7 +53,7 @@ public class Necromancer extends Mob {
|
|||
maxLvl = 14;
|
||||
|
||||
loot = new PotionOfHealing();
|
||||
lootChance = 0.2f; //see createloot
|
||||
lootChance = 0.2f; //see lootChance()
|
||||
|
||||
properties.add(Property.UNDEAD);
|
||||
|
||||
|
@ -84,13 +83,12 @@ public class Necromancer extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
lootChance *= ((6f - Dungeon.LimitedDrops.NECRO_HP.count) / 6f);
|
||||
super.rollToDropLoot();
|
||||
public float lootChance() {
|
||||
return super.lootChance() * ((6f - Dungeon.LimitedDrops.NECRO_HP.count) / 6f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot(){
|
||||
public Item createLoot(){
|
||||
Dungeon.LimitedDrops.NECRO_HP.count++;
|
||||
return super.createLoot();
|
||||
}
|
||||
|
|
|
@ -89,8 +89,8 @@ public class Piranha extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean surprisedBy(Char enemy) {
|
||||
if (enemy == Dungeon.hero && ((Hero)enemy).canSurpriseAttack()){
|
||||
public boolean surprisedBy(Char enemy, boolean attacking) {
|
||||
if (enemy == Dungeon.hero && (!attacking || ((Hero)enemy).canSurpriseAttack())){
|
||||
if (fieldOfView == null || fieldOfView.length != Dungeon.level.length()){
|
||||
fieldOfView = new boolean[Dungeon.level.length()];
|
||||
Dungeon.level.updateFieldOfView( this, fieldOfView );
|
||||
|
|
|
@ -103,7 +103,7 @@ public class Scorpio extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Class<?extends Potion> loot;
|
||||
do{
|
||||
loot = (Class<? extends Potion>) Random.oneOf(Generator.Category.POTION.classes);
|
||||
|
|
|
@ -48,7 +48,7 @@ public abstract class Shaman extends Mob {
|
|||
maxLvl = 16;
|
||||
|
||||
loot = Generator.Category.WAND;
|
||||
lootChance = 0.03f; //initially, see rollToDropLoot
|
||||
lootChance = 0.03f; //initially, see lootChance()
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,15 +72,14 @@ public abstract class Shaman extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
public float lootChance() {
|
||||
//each drop makes future drops 1/3 as likely
|
||||
// so loot chance looks like: 1/33, 1/100, 1/300, 1/900, etc.
|
||||
lootChance *= Math.pow(1/3f, Dungeon.LimitedDrops.SHAMAN_WAND.count);
|
||||
super.rollToDropLoot();
|
||||
return super.lootChance() * (float)Math.pow(1/3f, Dungeon.LimitedDrops.SHAMAN_WAND.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Dungeon.LimitedDrops.SHAMAN_WAND.count++;
|
||||
return super.createLoot();
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class Skeleton extends Mob {
|
|||
maxLvl = 10;
|
||||
|
||||
loot = Generator.Category.WEAPON;
|
||||
lootChance = 0.1667f; //by default, see rollToDropLoot()
|
||||
lootChance = 0.1667f; //by default, see lootChance()
|
||||
|
||||
properties.add(Property.UNDEAD);
|
||||
properties.add(Property.INORGANIC);
|
||||
|
@ -88,15 +88,14 @@ public class Skeleton extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
public float lootChance() {
|
||||
//each drop makes future drops 1/2 as likely
|
||||
// so loot chance looks like: 1/6, 1/12, 1/24, 1/48, etc.
|
||||
lootChance *= Math.pow(1/2f, Dungeon.LimitedDrops.SKELE_WEP.count);
|
||||
super.rollToDropLoot();
|
||||
return super.lootChance() * (float)Math.pow(1/2f, Dungeon.LimitedDrops.SKELE_WEP.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Dungeon.LimitedDrops.SKELE_WEP.count++;
|
||||
return super.createLoot();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public class Slime extends Mob {
|
|||
EXP = 4;
|
||||
maxLvl = 9;
|
||||
|
||||
lootChance = 0.2f; //by default, see rollToDropLoot()
|
||||
lootChance = 0.2f; //by default, see lootChance()
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,15 +64,14 @@ public class Slime extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
public float lootChance(){
|
||||
//each drop makes future drops 1/3 as likely
|
||||
// so loot chance looks like: 1/5, 1/15, 1/45, 1/135, etc.
|
||||
lootChance *= Math.pow(1/3f, Dungeon.LimitedDrops.SLIME_WEP.count);
|
||||
super.rollToDropLoot();
|
||||
return super.lootChance() * (float)Math.pow(1/3f, Dungeon.LimitedDrops.SLIME_WEP.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Dungeon.LimitedDrops.SLIME_WEP.count++;
|
||||
Generator.Category c = Generator.Category.WEP_T2;
|
||||
MeleeWeapon w = (MeleeWeapon) Reflection.newInstance(c.classes[Random.chances(c.probs)]);
|
||||
|
|
|
@ -163,7 +163,7 @@ public class Succubus extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Class<?extends Scroll> loot;
|
||||
do{
|
||||
loot = (Class<? extends Scroll>) Random.oneOf(Generator.Category.SCROLL.classes);
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AllyBuff;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ChampionEnemy;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
|
@ -54,7 +53,7 @@ public class Swarm extends Mob {
|
|||
flying = true;
|
||||
|
||||
loot = new PotionOfHealing();
|
||||
lootChance = 0.1667f; //by default, see rollToDropLoot()
|
||||
lootChance = 0.1667f; //by default, see lootChance()
|
||||
}
|
||||
|
||||
private static final float SPLIT_DELAY = 1f;
|
||||
|
@ -139,14 +138,13 @@ public class Swarm extends Mob {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
public float lootChance() {
|
||||
lootChance = 1f/(6 * (generation+1) );
|
||||
lootChance *= (5f - Dungeon.LimitedDrops.SWARM_HP.count) / 5f;
|
||||
super.rollToDropLoot();
|
||||
return super.lootChance() * (5f - Dungeon.LimitedDrops.SWARM_HP.count) / 5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot(){
|
||||
public Item createLoot(){
|
||||
Dungeon.LimitedDrops.SWARM_HP.count++;
|
||||
return super.createLoot();
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
|
|||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AllyBuff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Dread;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
|
@ -55,7 +54,7 @@ public class Thief extends Mob {
|
|||
maxLvl = 11;
|
||||
|
||||
loot = Random.oneOf(Generator.Category.RING, Generator.Category.ARTIFACT);
|
||||
lootChance = 0.03f; //initially, see rollToDropLoot
|
||||
lootChance = 0.03f; //initially, see lootChance()
|
||||
|
||||
WANDERING = new Wandering();
|
||||
FLEEING = new Fleeing();
|
||||
|
@ -93,6 +92,13 @@ public class Thief extends Mob {
|
|||
return super.attackDelay()*0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float lootChance() {
|
||||
//each drop makes future drops 1/3 as likely
|
||||
// so loot chance looks like: 1/33, 1/100, 1/300, 1/900, etc.
|
||||
return super.lootChance() * (float)Math.pow(1/3f, Dungeon.LimitedDrops.THEIF_MISC.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollToDropLoot() {
|
||||
if (item != null) {
|
||||
|
@ -101,14 +107,11 @@ public class Thief extends Mob {
|
|||
if (item instanceof Honeypot.ShatteredPot) ((Honeypot.ShatteredPot)item).dropPot( this, pos );
|
||||
item = null;
|
||||
}
|
||||
//each drop makes future drops 1/3 as likely
|
||||
// so loot chance looks like: 1/33, 1/100, 1/300, 1/900, etc.
|
||||
lootChance *= Math.pow(1/3f, Dungeon.LimitedDrops.THEIF_MISC.count);
|
||||
super.rollToDropLoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createLoot() {
|
||||
public Item createLoot() {
|
||||
Dungeon.LimitedDrops.THEIF_MISC.count++;
|
||||
return super.createLoot();
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ public class Warlock extends Mob implements Callback {
|
|||
public Item createLoot(){
|
||||
|
||||
// 1/6 chance for healing, scaling to 0 over 8 drops
|
||||
if (Random.Int(2) == 0 && Random.Int(8) > Dungeon.LimitedDrops.WARLOCK_HP.count ){
|
||||
if (Random.Int(3) == 0 && Random.Int(8) > Dungeon.LimitedDrops.WARLOCK_HP.count ){
|
||||
Dungeon.LimitedDrops.WARLOCK_HP.count++;
|
||||
return new PotionOfHealing();
|
||||
} else {
|
||||
|
|
|
@ -64,10 +64,6 @@ public class Gold extends Item {
|
|||
Statistics.goldCollected += quantity;
|
||||
Badges.validateGoldCollected();
|
||||
|
||||
MasterThievesArmband.Thievery thievery = hero.buff(MasterThievesArmband.Thievery.class);
|
||||
if (thievery != null)
|
||||
thievery.collect(quantity);
|
||||
|
||||
GameScene.pickUp( this, pos );
|
||||
hero.sprite.showStatus( CharSprite.NEUTRAL, TXT_VALUE, quantity );
|
||||
hero.spendAndNext( TIME_TO_PICK_UP );
|
||||
|
|
|
@ -21,14 +21,36 @@
|
|||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.items.artifacts;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.CounterBuff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Surprise;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEnergy;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Callback;
|
||||
import com.watabou.utils.PathFinder;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MasterThievesArmband extends Artifact {
|
||||
|
||||
{
|
||||
|
@ -37,9 +59,132 @@ public class MasterThievesArmband extends Artifact {
|
|||
levelCap = 10;
|
||||
|
||||
charge = 0;
|
||||
partialCharge = 0;
|
||||
chargeCap = 5+level()/2;
|
||||
|
||||
defaultAction = AC_STEAL;
|
||||
}
|
||||
|
||||
private int exp = 0;
|
||||
public static final String AC_STEAL = "STEAL";
|
||||
|
||||
@Override
|
||||
public ArrayList<String> actions(Hero hero) {
|
||||
ArrayList<String> actions = super.actions(hero);
|
||||
if (isEquipped(hero) && charge > 0 && !cursed) actions.add(AC_STEAL);
|
||||
return actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Hero hero, String action) {
|
||||
super.execute(hero, action);
|
||||
if (action.equals(AC_STEAL)){
|
||||
|
||||
curUser = hero;
|
||||
|
||||
if (!isEquipped( hero )) {
|
||||
GLog.i( Messages.get(Artifact.class, "need_to_equip") );
|
||||
usesTargeting = false;
|
||||
|
||||
} else if (charge < 1) {
|
||||
GLog.i( Messages.get(this, "no_charge") );
|
||||
usesTargeting = false;
|
||||
|
||||
} else if (cursed) {
|
||||
GLog.w( Messages.get(this, "cursed") );
|
||||
usesTargeting = false;
|
||||
|
||||
} else {
|
||||
usesTargeting = true;
|
||||
GameScene.selectCell(targeter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private CellSelector.Listener targeter = new CellSelector.Listener(){
|
||||
|
||||
@Override
|
||||
public void onSelect(Integer target) {
|
||||
|
||||
if (target == null) {
|
||||
return;
|
||||
} else if (!Dungeon.level.adjacent(curUser.pos, target) || Actor.findChar(target) == null){
|
||||
GLog.w( Messages.get(MasterThievesArmband.class, "no_target") );
|
||||
} else {
|
||||
Char ch = Actor.findChar(target);
|
||||
if (ch instanceof Shopkeeper){
|
||||
GLog.w( Messages.get(MasterThievesArmband.class, "steal_shopkeeper") );
|
||||
} else if (ch.alignment != Char.Alignment.ENEMY){
|
||||
GLog.w( Messages.get(MasterThievesArmband.class, "no_target") );
|
||||
} else if (ch instanceof Mob) {
|
||||
curUser.busy();
|
||||
curUser.sprite.attack(target, new Callback() {
|
||||
@Override
|
||||
public void call() {
|
||||
Sample.INSTANCE.play(Assets.Sounds.HIT);
|
||||
|
||||
boolean surprised = ((Mob) ch).surprisedBy(curUser, false);
|
||||
float lootMultiplier = 1f + 0.1f*level();
|
||||
int debuffDuration = 3 + level()/2;
|
||||
|
||||
if (surprised){
|
||||
lootMultiplier += 0.5f;
|
||||
Surprise.hit(ch);
|
||||
Sample.INSTANCE.play(Assets.Sounds.HIT_STRONG);
|
||||
debuffDuration += 2;
|
||||
exp += 2;
|
||||
}
|
||||
|
||||
float lootChance = ((Mob) ch).lootChance() * lootMultiplier;
|
||||
if (ch.buff(StolenTracker.class) != null || lootChance == 0){
|
||||
GLog.w(Messages.get(MasterThievesArmband.class, "no_steal"));
|
||||
} else if (Random.Float() <= lootChance){
|
||||
Item loot = ((Mob) ch).createLoot();
|
||||
if (loot.doPickUp(curUser)){
|
||||
//item collection happens instantly
|
||||
curUser.spend(-TIME_TO_PICK_UP);
|
||||
} else {
|
||||
Dungeon.level.drop( loot, curUser.pos ).sprite.drop();
|
||||
}
|
||||
GLog.i(Messages.get(MasterThievesArmband.class, "stole_item", loot.name()));
|
||||
Buff.affect(ch, StolenTracker.class).setItemStolen(true);
|
||||
} else {
|
||||
GLog.i(Messages.get(MasterThievesArmband.class, "failed_steal"));
|
||||
Buff.affect(ch, StolenTracker.class).setItemStolen(false);
|
||||
}
|
||||
|
||||
Buff.prolong(ch, Blindness.class, debuffDuration);
|
||||
Buff.prolong(ch, Cripple.class, debuffDuration);
|
||||
|
||||
charge--;
|
||||
exp += 3;
|
||||
Talent.onArtifactUsed(Dungeon.hero);
|
||||
while (exp >= (10 + Math.round(3.33f * level())) && level() < levelCap) {
|
||||
exp -= 10 + Math.round(3.33f * level());
|
||||
GLog.p(Messages.get(MasterThievesArmband.class, "level_up"));
|
||||
upgrade();
|
||||
}
|
||||
Item.updateQuickslot();
|
||||
curUser.next();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String prompt() {
|
||||
return Messages.get(MasterThievesArmband.class, "prompt");
|
||||
}
|
||||
};
|
||||
|
||||
//counter of 0 for attempt but no success, 1 for success
|
||||
public static class StolenTracker extends CounterBuff {
|
||||
public void setItemStolen(boolean stolen){ if (stolen) countUp(1); }
|
||||
public boolean itemWasStolen(){ return count() > 0; }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArtifactBuff passiveBuff() {
|
||||
|
@ -48,8 +193,22 @@ public class MasterThievesArmband extends Artifact {
|
|||
|
||||
@Override
|
||||
public void charge(Hero target, float amount) {
|
||||
charge += Math.round(10*amount);
|
||||
partialCharge += 0.1f * amount;
|
||||
partialCharge = Math.min(partialCharge, chargeCap - charge);
|
||||
while (partialCharge > 1f){
|
||||
charge++;
|
||||
partialCharge--;
|
||||
updateQuickslot();
|
||||
if (charge == chargeCap){
|
||||
GLog.p( Messages.get(MasterThievesArmband.class, "full") );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item upgrade() {
|
||||
chargeCap = 5 + (level()+1)/2;
|
||||
return super.upgrade();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,67 +223,90 @@ public class MasterThievesArmband extends Artifact {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
public class Thievery extends ArtifactBuff{
|
||||
public void collect(int gold){
|
||||
if (!cursed) {
|
||||
charge += gold/2 * RingOfEnergy.artifactChargeMultiplier(target);
|
||||
@Override
|
||||
public void restoreFromBundle(Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
//conversion for old armband on pre-1.2.0 saves
|
||||
if (exp > Math.round(10 + level()*3.33f)){
|
||||
exp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
charge *= 0.95;
|
||||
super.detach();
|
||||
}
|
||||
public class Thievery extends ArtifactBuff {
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (cursed) {
|
||||
|
||||
if (Dungeon.gold > 0 && Random.Int(6) == 0){
|
||||
if (cursed && Dungeon.gold > 0 && Random.Int(5) == 0){
|
||||
Dungeon.gold--;
|
||||
}
|
||||
|
||||
spend(TICK);
|
||||
return true;
|
||||
} else {
|
||||
return super.act();
|
||||
}
|
||||
|
||||
public void gainCharge(float levelPortion) {
|
||||
if (cursed) return;
|
||||
|
||||
if (charge < chargeCap){
|
||||
float chargeGain = 3f * levelPortion;
|
||||
|
||||
partialCharge += chargeGain;
|
||||
while (partialCharge > 1f){
|
||||
partialCharge--;
|
||||
charge++;
|
||||
updateQuickslot();
|
||||
|
||||
if (charge == chargeCap){
|
||||
GLog.p( Messages.get(MasterThievesArmband.class, "full") );
|
||||
partialCharge = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean steal(int value){
|
||||
if (value <= charge){
|
||||
charge -= value;
|
||||
exp += value;
|
||||
} else {
|
||||
float chance = stealChance(value);
|
||||
if (Random.Float() > chance)
|
||||
partialCharge = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean steal(Item item){
|
||||
int chargesUsed = chargesToUse(item);
|
||||
float stealChance = stealChance(item);
|
||||
if (Random.Float() > stealChance){
|
||||
return false;
|
||||
else {
|
||||
if (chance <= 1)
|
||||
charge = 0;
|
||||
else
|
||||
//removes the charge it took you to reach 100%
|
||||
charge -= charge/chance;
|
||||
exp += value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
charge -= chargesUsed;
|
||||
exp += 4 * chargesUsed;
|
||||
GLog.i(Messages.get(MasterThievesArmband.class, "stole_item", item.name()));
|
||||
|
||||
Talent.onArtifactUsed(Dungeon.hero);
|
||||
while(exp >= (250 + 50*level()) && level() < levelCap) {
|
||||
exp -= (250 + 50*level());
|
||||
while (exp >= (10 + Math.round(3.33f * level())) && level() < levelCap) {
|
||||
exp -= 10 + Math.round(3.33f * level());
|
||||
GLog.p(Messages.get(MasterThievesArmband.class, "level_up"));
|
||||
upgrade();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public float stealChance(int value){
|
||||
//get lvl*50 gold or lvl*3.33% item value of free charge, whichever is less.
|
||||
int chargeBonus = Math.min(level()*50, (value*level())/30);
|
||||
return (((float)charge + chargeBonus)/value);
|
||||
public float stealChance(Item item){
|
||||
int chargesUsed = chargesToUse(item);
|
||||
float val = chargesUsed * (10 + level()/2f);
|
||||
return Math.min(1f, val/item.value());
|
||||
}
|
||||
|
||||
public int chargesToUse(Item item){
|
||||
int value = item.value();
|
||||
float valUsing = 0;
|
||||
int chargesUsed = 0;
|
||||
while (valUsing < value && chargesUsed < charge){
|
||||
valUsing += 10 + level()/2f;
|
||||
chargesUsed++;
|
||||
}
|
||||
return chargesUsed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -129,12 +129,13 @@ public class WndTradeItem extends WndInfoItem {
|
|||
pos = btnBuy.bottom();
|
||||
|
||||
final MasterThievesArmband.Thievery thievery = Dungeon.hero.buff(MasterThievesArmband.Thievery.class);
|
||||
if (thievery != null && !thievery.isCursed()) {
|
||||
final float chance = thievery.stealChance(price);
|
||||
RedButton btnSteal = new RedButton(Messages.get(this, "steal", Math.min(100, (int) (chance * 100)))) {
|
||||
if (thievery != null && !thievery.isCursed() && thievery.chargesToUse(item) > 0) {
|
||||
final float chance = thievery.stealChance(item);
|
||||
final int chargesToUse = thievery.chargesToUse(item);
|
||||
RedButton btnSteal = new RedButton(Messages.get(this, "steal", Math.min(100, (int) (chance * 100)), chargesToUse), 6) {
|
||||
@Override
|
||||
protected void onClick() {
|
||||
if (thievery.steal(price)) {
|
||||
if (thievery.steal(item)) {
|
||||
Hero hero = Dungeon.hero;
|
||||
Item item = heap.pickUp();
|
||||
hide();
|
||||
|
|
Loading…
Reference in New Issue
Block a user