V0.1.0 Partial Commit

changed package and application names to differentiate from main PD
release
This commit is contained in:
Evan Debenham
2014-08-03 14:46:22 -04:00
parent 65dd9c2dc0
commit aed303672a
474 changed files with 3468 additions and 3458 deletions
@@ -0,0 +1,106 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.io.IOException;
import java.util.ArrayList;
import com.watabou.noosa.Game;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.scenes.AmuletScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class Amulet extends Item {
private static final String AC_END = "END THE GAME";
{
name = "Amulet of Yendor";
image = ItemSpriteSheet.AMULET;
unique = true;
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_END );
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action == AC_END) {
showAmuletScene( false );
} else {
super.execute( hero, action );
}
}
@Override
public boolean doPickUp( Hero hero ) {
if (super.doPickUp( hero )) {
if (!Statistics.amuletObtained) {
Statistics.amuletObtained = true;
Dungeon.win( ResultDescriptions.WIN );
Badges.validateVictory();
showAmuletScene( true );
}
return true;
} else {
return false;
}
}
private void showAmuletScene( boolean showText ) {
try {
Dungeon.saveAll();
AmuletScene.noText = !showText;
Game.switchScene( AmuletScene.class );
} catch (IOException e) {
}
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public String info() {
return
"The Amulet of Yendor is the most powerful known artifact of unknown origin. It is said that the amulet " +
"is able to fulfil any wish if its owner's will-power is strong enough to \"persuade\" it to do it.";
}
}
@@ -0,0 +1,51 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class Ankh extends Item {
{
stackable = true;
name = "Ankh";
image = ItemSpriteSheet.ANKH;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public String info() {
return
"The ancient symbol of immortality grants an ability to return to life after death. " +
"Upon resurrection all non-equipped items are lost.";
}
@Override
public int price() {
return 50 * quantity;
}
}
@@ -0,0 +1,124 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClassArmor;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
public class ArmorKit extends Item {
private static final String TXT_SELECT_ARMOR = "Select an armor to upgrade";
private static final String TXT_UPGRADED = "you applied the armor kit to upgrade your %s";
private static final float TIME_TO_UPGRADE = 2;
private static final String AC_APPLY = "APPLY";
{
name = "armor kit";
image = ItemSpriteSheet.KIT;
unique = true;
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_APPLY );
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action == AC_APPLY) {
curUser = hero;
GameScene.selectItem( itemSelector, WndBag.Mode.ARMOR, TXT_SELECT_ARMOR );
} else {
super.execute( hero, action );
}
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
private void upgrade( Armor armor ) {
detach( curUser.belongings.backpack );
curUser.sprite.centerEmitter().start( Speck.factory( Speck.KIT ), 0.05f, 10 );
curUser.spend( TIME_TO_UPGRADE );
curUser.busy();
GLog.w( TXT_UPGRADED, armor.name() );
ClassArmor classArmor = ClassArmor.upgrade( curUser, armor );
if (curUser.belongings.armor == armor) {
curUser.belongings.armor = classArmor;
((HeroSprite)curUser.sprite).updateArmor();
} else {
armor.detach( curUser.belongings.backpack );
classArmor.collect( curUser.belongings.backpack );
}
curUser.sprite.operate( curUser.pos );
Sample.INSTANCE.play( Assets.SND_EVOKE );
}
@Override
public String info() {
return
"Using this kit of small tools and materials anybody can transform any armor into an \"epic armor\", " +
"which will keep all properties of the original armor, but will also provide its wearer a special ability " +
"depending on his class. No skills in tailoring, leatherworking or blacksmithing are required.";
}
private final WndBag.Listener itemSelector = new WndBag.Listener() {
@Override
public void onSelect( Item item ) {
if (item != null) {
ArmorKit.this.upgrade( (Armor)item );
}
}
};
}
@@ -0,0 +1,187 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShaftParticle;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.watabou.utils.Bundle;
public class DewVial extends Item {
private static final int MAX_VOLUME = 10;
private static final String AC_DRINK = "DRINK";
private static final float TIME_TO_DRINK = 1f;
private static final String TXT_VALUE = "%+dHP";
private static final String TXT_STATUS = "%d/%d";
private static final String TXT_AUTO_DRINK = "The dew vial was emptied to heal your wounds.";
private static final String TXT_COLLECTED = "You collected a dewdrop into your dew vial.";
private static final String TXT_FULL = "Your dew vial is full!";
private static final String TXT_EMPTY = "Your dew vial is empty!";
{
name = "dew vial";
image = ItemSpriteSheet.VIAL;
defaultAction = AC_DRINK;
unique = true;
}
private int volume = 0;
private static final String VOLUME = "volume";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( VOLUME, volume );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
volume = bundle.getInt( VOLUME );
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
if (volume > 0) {
actions.add( AC_DRINK );
}
return actions;
}
private static final double NUM = 20;
private static final double POW = Math.log10( NUM );
@Override
public void execute( final Hero hero, String action ) {
if (action.equals( AC_DRINK )) {
if (volume > 0) {
int value = (int)Math.ceil( Math.pow( volume, POW ) / NUM * hero.HT );
int effect = Math.min( hero.HT - hero.HP, value );
if (effect > 0) {
hero.HP += effect;
hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), volume > 5 ? 2 : 1 );
hero.sprite.showStatus( CharSprite.POSITIVE, TXT_VALUE, effect );
}
volume = 0;
hero.spend( TIME_TO_DRINK );
hero.busy();
Sample.INSTANCE.play( Assets.SND_DRINK );
hero.sprite.operate( hero.pos );
updateQuickslot();
} else {
GLog.w( TXT_EMPTY );
}
} else {
super.execute( hero, action );
}
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
public boolean isFull() {
return volume >= MAX_VOLUME;
}
public void collectDew( Dewdrop dew ) {
GLog.i( TXT_COLLECTED );
volume += dew.quantity;
if (volume >= MAX_VOLUME) {
volume = MAX_VOLUME;
GLog.p( TXT_FULL );
}
updateQuickslot();
}
public void fill() {
volume = MAX_VOLUME;
updateQuickslot();
}
public static void autoDrink( Hero hero ) {
DewVial vial = hero.belongings.getItem( DewVial.class );
if (vial != null && vial.isFull()) {
vial.execute( hero );
hero.sprite.emitter().start( ShaftParticle.FACTORY, 0.2f, 3 );
GLog.w( TXT_AUTO_DRINK );
}
}
private static final Glowing WHITE = new Glowing( 0xFFFFCC );
@Override
public Glowing glowing() {
return isFull() ? WHITE : null;
}
@Override
public String status() {
return Utils.format( TXT_STATUS, volume, MAX_VOLUME );
}
@Override
public String info() {
return
"You can store excess dew in this tiny vessel for drinking it later. " +
"If the vial is full, in a moment of deadly peril the dew will be " +
"consumed automatically.";
}
@Override
public String toString() {
return super.toString() + " (" + status() + ")" ;
}
}
@@ -0,0 +1,75 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class Dewdrop extends Item {
private static final String TXT_VALUE = "%+dHP";
{
name = "dewdrop";
image = ItemSpriteSheet.DEWDROP;
stackable = true;
}
@Override
public boolean doPickUp( Hero hero ) {
DewVial vial = hero.belongings.getItem( DewVial.class );
if (hero.HP < hero.HT || vial == null || vial.isFull()) {
int value = 1 + (Dungeon.depth - 1) / 5;
if (hero.heroClass == HeroClass.HUNTRESS) {
value++;
}
int effect = Math.min( hero.HT - hero.HP, value * quantity );
if (effect > 0) {
hero.HP += effect;
hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 );
hero.sprite.showStatus( CharSprite.POSITIVE, TXT_VALUE, effect );
}
} else if (vial != null) {
vial.collectDew( this );
}
Sample.INSTANCE.play( Assets.SND_DEWDROP );
hero.spendAndNext( TIME_TO_PICK_UP );
return true;
}
@Override
public String info() {
return "A crystal clear dewdrop.";
}
}
@@ -0,0 +1,68 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
public abstract class EquipableItem extends Item {
public static final String AC_EQUIP = "EQUIP";
public static final String AC_UNEQUIP = "UNEQUIP";
@Override
public void execute( Hero hero, String action ) {
if (action.equals( AC_EQUIP )) {
doEquip( hero );
} else if (action.equals( AC_UNEQUIP )) {
doUnequip( hero, true );
} else {
super.execute( hero, action );
}
}
@Override
public void doDrop( Hero hero ) {
if (!isEquipped( hero ) || doUnequip( hero, false )) {
super.doDrop( hero );
}
}
@Override
public void cast( final Hero user, int dst ) {
if (isEquipped( user )) {
if (quantity == 1 && !this.doUnequip( user, false )) {
return;
}
}
super.cast( user, dst );
}
protected static void equipCursed( Hero hero ) {
hero.sprite.emitter().burst( ShadowParticle.CURSE, 6 );
Sample.INSTANCE.play( Assets.SND_CURSED );
}
public abstract boolean doEquip( Hero hero );
public abstract boolean doUnequip( Hero hero, boolean collect );
}
@@ -0,0 +1,263 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.HashMap;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker.Rotberry;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.*;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
import com.shatteredpixel.shatteredpixeldungeon.items.food.Food;
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
import com.shatteredpixel.shatteredpixeldungeon.items.food.Pasty;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.*;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.*;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.*;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.*;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.*;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.*;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.*;
import com.shatteredpixel.shatteredpixeldungeon.plants.*;
import com.watabou.utils.Random;
public class Generator {
public static enum Category {
WEAPON ( 15, Weapon.class ),
ARMOR ( 10, Armor.class ),
POTION ( 50, Potion.class ),
SCROLL ( 40, Scroll.class ),
WAND ( 4, Wand.class ),
RING ( 2, Ring.class ),
SEED ( 5, Plant.Seed.class ),
FOOD ( 0, Food.class ),
GOLD ( 50, Gold.class );
public Class<?>[] classes;
public float[] probs;
public float prob;
public Class<? extends Item> superClass;
private Category( float prob, Class<? extends Item> superClass ) {
this.prob = prob;
this.superClass = superClass;
}
public static int order( Item item ) {
for (int i=0; i < values().length; i++) {
if (values()[i].superClass.isInstance( item )) {
return i;
}
}
return item instanceof Bag ? Integer.MAX_VALUE : Integer.MAX_VALUE - 1;
}
};
private static HashMap<Category,Float> categoryProbs = new HashMap<Generator.Category, Float>();
static {
Category.GOLD.classes = new Class<?>[]{
Gold.class };
Category.GOLD.probs = new float[]{ 1 };
Category.SCROLL.classes = new Class<?>[]{
ScrollOfIdentify.class,
ScrollOfTeleportation.class,
ScrollOfRemoveCurse.class,
ScrollOfUpgrade.class,
ScrollOfRecharging.class,
ScrollOfMagicMapping.class,
ScrollOfRage.class,
ScrollOfTerror.class,
ScrollOfLullaby.class,
ScrollOfWeaponUpgrade.class,
ScrollOfPsionicBlast.class,
ScrollOfMirrorImage.class };
Category.SCROLL.probs = new float[]{ 30, 10, 15, 0, 10, 15, 12, 8, 8, 0, 4, 6 };
Category.POTION.classes = new Class<?>[]{
PotionOfHealing.class,
PotionOfExperience.class,
PotionOfToxicGas.class,
PotionOfParalyticGas.class,
PotionOfLiquidFlame.class,
PotionOfLevitation.class,
PotionOfStrength.class,
PotionOfMindVision.class,
PotionOfPurity.class,
PotionOfInvisibility.class,
PotionOfMight.class,
PotionOfFrost.class };
Category.POTION.probs = new float[]{ 45, 4, 15, 10, 15, 10, 0, 20, 12, 10, 0, 10 };
Category.WAND.classes = new Class<?>[]{
WandOfTeleportation.class,
WandOfSlowness.class,
WandOfFirebolt.class,
WandOfRegrowth.class,
WandOfPoison.class,
WandOfBlink.class,
WandOfLightning.class,
WandOfAmok.class,
WandOfTelekinesis.class,
WandOfFlock.class,
WandOfMagicMissile.class,
WandOfDisintegration.class,
WandOfAvalanche.class };
Category.WAND.probs = new float[]{ 10, 10, 15, 6, 10, 11, 15, 10, 6, 10, 0, 5, 5 };
Category.WEAPON.classes = new Class<?>[]{
Dagger.class,
Knuckles.class,
Quarterstaff.class,
Spear.class,
Mace.class,
Sword.class,
Longsword.class,
BattleAxe.class,
WarHammer.class,
Glaive.class,
ShortSword.class,
Dart.class,
Javelin.class,
IncendiaryDart.class,
CurareDart.class,
Shuriken.class,
Boomerang.class,
Tamahawk.class };
Category.WEAPON.probs = new float[]{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1 };
Category.ARMOR.classes = new Class<?>[]{
ClothArmor.class,
LeatherArmor.class,
MailArmor.class,
ScaleArmor.class,
PlateArmor.class };
Category.ARMOR.probs = new float[]{ 1, 1, 1, 1, 1 };
Category.FOOD.classes = new Class<?>[]{
Food.class,
Pasty.class,
MysteryMeat.class };
Category.FOOD.probs = new float[]{ 4, 1, 0 };
Category.RING.classes = new Class<?>[]{
RingOfMending.class,
RingOfDetection.class,
RingOfShadows.class,
RingOfPower.class,
RingOfHerbalism.class,
RingOfAccuracy.class,
RingOfEvasion.class,
RingOfSatiety.class,
RingOfHaste.class,
RingOfElements.class,
RingOfHaggler.class,
RingOfThorns.class };
Category.RING.probs = new float[]{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 };
Category.SEED.classes = new Class<?>[]{
Firebloom.Seed.class,
Icecap.Seed.class,
Sorrowmoss.Seed.class,
Blindweed.Seed.class,
Sungrass.Seed.class,
Earthroot.Seed.class,
Fadeleaf.Seed.class,
Rotberry.Seed.class };
Category.SEED.probs = new float[]{ 1, 1, 1, 1, 1, 1, 1, 0 };
}
public static void reset() {
for (Category cat : Category.values()) {
categoryProbs.put( cat, cat.prob );
}
}
public static Item random() {
return random( Random.chances( categoryProbs ) );
}
public static Item random( Category cat ) {
try {
categoryProbs.put( cat, categoryProbs.get( cat ) / 2 );
switch (cat) {
case ARMOR:
return randomArmor();
case WEAPON:
return randomWeapon();
default:
return ((Item)cat.classes[Random.chances( cat.probs )].newInstance()).random();
}
} catch (Exception e) {
return null;
}
}
public static Item random( Class<? extends Item> cl ) {
try {
return ((Item)cl.newInstance()).random();
} catch (Exception e) {
return null;
}
}
public static Armor randomArmor() throws Exception {
int curStr = Hero.STARTING_STR + Dungeon.potionOfStrength;
Category cat = Category.ARMOR;
Armor a1 = (Armor)cat.classes[Random.chances( cat.probs )].newInstance();
Armor a2 = (Armor)cat.classes[Random.chances( cat.probs )].newInstance();
a1.random();
a2.random();
return Math.abs( curStr - a1.STR ) < Math.abs( curStr - a2.STR ) ? a1 : a2;
}
public static Weapon randomWeapon() throws Exception {
int curStr = Hero.STARTING_STR + Dungeon.potionOfStrength;
Category cat = Category.WEAPON;
Weapon w1 = (Weapon)cat.classes[Random.chances( cat.probs )].newInstance();
Weapon w2 = (Weapon)cat.classes[Random.chances( cat.probs )].newInstance();
w1.random();
w2.random();
return Math.abs( curStr - w1.STR ) < Math.abs( curStr - w2.STR ) ? w1 : w2;
}
}
@@ -0,0 +1,118 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class Gold extends Item {
private static final String TXT_COLLECT = "Collect gold coins to spend them later in a shop.";
private static final String TXT_INFO = "A pile of %d gold coins. " + TXT_COLLECT;
private static final String TXT_INFO_1 = "One gold coin. " + TXT_COLLECT;
private static final String TXT_VALUE = "%+d";
{
name = "gold";
image = ItemSpriteSheet.GOLD;
stackable = true;
}
public Gold() {
this( 1 );
}
public Gold( int value ) {
this.quantity = value;
}
@Override
public ArrayList<String> actions( Hero hero ) {
return new ArrayList<String>();
}
@Override
public boolean doPickUp( Hero hero ) {
Dungeon.gold += quantity;
Statistics.goldCollected += quantity;
Badges.validateGoldCollected();
GameScene.pickUp( this );
hero.sprite.showStatus( CharSprite.NEUTRAL, TXT_VALUE, quantity );
hero.spendAndNext( TIME_TO_PICK_UP );
Sample.INSTANCE.play( Assets.SND_GOLD, 1, 1, Random.Float( 0.9f, 1.1f ) );
return true;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public String info() {
switch (quantity) {
case 0:
return TXT_COLLECT;
case 1:
return TXT_INFO_1;
default:
return Utils.format( TXT_INFO, quantity );
}
}
@Override
public Item random() {
quantity = Random.Int( 20 + Dungeon.depth * 10, 40 + Dungeon.depth * 20 );
return this;
}
private static final String VALUE = "value";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( VALUE, quantity );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle(bundle);
quantity = bundle.getInt( VALUE );
}
}
@@ -0,0 +1,337 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.Collection;
import java.util.LinkedList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.food.ChargrilledMeat;
import com.shatteredpixel.shatteredpixeldungeon.items.food.FrozenCarpaccio;
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
import com.shatteredpixel.shatteredpixeldungeon.plants.Plant.Seed;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.watabou.utils.Bundlable;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class Heap implements Bundlable {
private static final int SEEDS_TO_POTION = 3;
public enum Type {
HEAP,
FOR_SALE,
CHEST,
LOCKED_CHEST,
CRYSTAL_CHEST,
TOMB,
SKELETON
}
public Type type = Type.HEAP;
public int pos = 0;
public ItemSprite sprite;
protected LinkedList<Item> items = new LinkedList<Item>();
public int image() {
switch (type) {
case HEAP:
case FOR_SALE:
return size() > 0 ? items.peek().image() : 0;
case CHEST:
return ItemSpriteSheet.CHEST;
case LOCKED_CHEST:
return ItemSpriteSheet.LOCKED_CHEST;
case CRYSTAL_CHEST:
return ItemSpriteSheet.CRYSTAL_CHEST;
case TOMB:
return ItemSpriteSheet.TOMB;
case SKELETON:
return ItemSpriteSheet.BONES;
default:
return 0;
}
}
public ItemSprite.Glowing glowing() {
return (type == Type.HEAP || type == Type.FOR_SALE) && items.size() > 0 ? items.peek().glowing() : null;
}
public void open( Hero hero ) {
switch (type) {
case TOMB:
Wraith.spawnAround( hero.pos );
break;
case SKELETON:
CellEmitter.center( pos ).start( Speck.factory( Speck.RATTLE ), 0.1f, 3 );
for (Item item : items) {
if (item.cursed) {
if (Wraith.spawnAt( pos ) == null) {
hero.sprite.emitter().burst( ShadowParticle.CURSE, 6 );
hero.damage( hero.HP / 2, this );
}
Sample.INSTANCE.play( Assets.SND_CURSED );
break;
}
}
break;
default:
}
type = Type.HEAP;
sprite.link();
sprite.drop();
}
public int size() {
return items.size();
}
public Item pickUp() {
Item item = items.removeFirst();
if (items.isEmpty()) {
destroy();
} else if (sprite != null) {
sprite.view( image(), glowing() );
}
return item;
}
public Item peek() {
return items.peek();
}
public void drop( Item item ) {
if (item.stackable) {
for (Item i : items) {
if (i.isSimilar( item )) {
i.quantity += item.quantity;
item = i;
break;
}
}
items.remove( item );
}
if (item instanceof Dewdrop) {
items.add( item );
} else {
items.addFirst( item );
}
if (sprite != null) {
sprite.view( image(), glowing() );
}
}
public void replace( Item a, Item b ) {
int index = items.indexOf( a );
if (index != -1) {
items.remove( index );
items.add( index, b );
}
}
public void burn() {
if (type != Type.HEAP) {
return;
}
boolean burnt = false;
boolean evaporated = false;
for (Item item : items.toArray( new Item[0] )) {
if (item instanceof Scroll) {
items.remove( item );
burnt = true;
} else if (item instanceof Dewdrop) {
items.remove( item );
evaporated = true;
} else if (item instanceof MysteryMeat) {
replace( item, ChargrilledMeat.cook( (MysteryMeat)item ) );
burnt = true;
}
}
if (burnt || evaporated) {
if (Dungeon.visible[pos]) {
if (burnt) {
burnFX( pos );
} else {
evaporateFX( pos );
}
}
if (isEmpty()) {
destroy();
} else if (sprite != null) {
sprite.view( image(), glowing() );
}
}
}
public void freeze() {
if (type != Type.HEAP) {
return;
}
boolean frozen = false;
for (Item item : items.toArray( new Item[0] )) {
if (item instanceof MysteryMeat) {
replace( item, FrozenCarpaccio.cook( (MysteryMeat)item ) );
frozen = true;
}
}
if (frozen) {
if (isEmpty()) {
destroy();
} else if (sprite != null) {
sprite.view( image(), glowing() );
}
}
}
public Item transmute() {
CellEmitter.get( pos ).burst( Speck.factory( Speck.BUBBLE ), 3 );
Splash.at( pos, 0xFFFFFF, 3 );
float chances[] = new float[items.size()];
int count = 0;
int index = 0;
for (Item item : items) {
if (item instanceof Seed) {
count += item.quantity;
chances[index++] = item.quantity;
} else {
count = 0;
break;
}
}
if (count >= SEEDS_TO_POTION) {
CellEmitter.get( pos ).burst( Speck.factory( Speck.WOOL ), 6 );
Sample.INSTANCE.play( Assets.SND_PUFF );
if (Random.Int( count ) == 0) {
CellEmitter.center( pos ).burst( Speck.factory( Speck.EVOKE ), 3 );
destroy();
Statistics.potionsCooked++;
Badges.validatePotionsCooked();
return Generator.random( Generator.Category.POTION );
} else {
Seed proto = (Seed)items.get( Random.chances( chances ) );
Class<? extends Item> itemClass = proto.alchemyClass;
destroy();
Statistics.potionsCooked++;
Badges.validatePotionsCooked();
if (itemClass == null) {
return Generator.random( Generator.Category.POTION );
} else {
try {
return itemClass.newInstance();
} catch (Exception e) {
return null;
}
}
}
} else {
return null;
}
}
public static void burnFX( int pos ) {
CellEmitter.get( pos ).burst( ElmoParticle.FACTORY, 6 );
Sample.INSTANCE.play( Assets.SND_BURNING );
}
public static void evaporateFX( int pos ) {
CellEmitter.get( pos ).burst( Speck.factory( Speck.STEAM ), 5 );
}
public boolean isEmpty() {
return items == null || items.size() == 0;
}
public void destroy() {
Dungeon.level.heaps.remove( this.pos );
if (sprite != null) {
sprite.kill();
}
items.clear();
items = null;
}
private static final String POS = "pos";
private static final String TYPE = "type";
private static final String ITEMS = "items";
@SuppressWarnings("unchecked")
@Override
public void restoreFromBundle( Bundle bundle ) {
pos = bundle.getInt( POS );
type = Type.valueOf( bundle.getString( TYPE ) );
items = new LinkedList<Item>( (Collection<? extends Item>) bundle.getCollection( ITEMS ) );
}
@Override
public void storeInBundle( Bundle bundle ) {
bundle.put( POS, pos );
bundle.put( TYPE, type.toString() );
bundle.put( ITEMS, items );
}
}
@@ -0,0 +1,463 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SnipersMark;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.MissileSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlot;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.watabou.utils.Bundlable;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
public class Item implements Bundlable {
private static final String TXT_PACK_FULL = "Your pack is too full for the %s";
private static final String TXT_TO_STRING = "%s";
private static final String TXT_TO_STRING_X = "%s x%d";
private static final String TXT_TO_STRING_LVL = "%s%+d";
private static final String TXT_TO_STRING_LVL_X = "%s%+d x%d";
protected static final float TIME_TO_THROW = 1.0f;
protected static final float TIME_TO_PICK_UP = 1.0f;
protected static final float TIME_TO_DROP = 0.5f;
public static final String AC_DROP = "DROP";
public static final String AC_THROW = "THROW";
public String defaultAction;
protected String name = "smth";
protected int image = 0;
public boolean stackable = false;
protected int quantity = 1;
public int level = 0;
public boolean levelKnown = false;
public boolean cursed;
public boolean cursedKnown;
// Unique items persist through revival
public boolean unique = false;
private static Comparator<Item> itemComparator = new Comparator<Item>() {
@Override
public int compare( Item lhs, Item rhs ) {
return Generator.Category.order( lhs ) - Generator.Category.order( rhs );
}
};
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = new ArrayList<String>();
actions.add( AC_DROP );
actions.add( AC_THROW );
return actions;
}
public boolean doPickUp( Hero hero ) {
if (collect( hero.belongings.backpack )) {
GameScene.pickUp( this );
Sample.INSTANCE.play( Assets.SND_ITEM );
hero.spendAndNext( TIME_TO_PICK_UP );
return true;
} else {
return false;
}
}
public void doDrop( Hero hero ) {
hero.spendAndNext( TIME_TO_DROP );
Dungeon.level.drop( detachAll( hero.belongings.backpack ), hero.pos ).sprite.drop( hero.pos );
}
public void doThrow( Hero hero ) {
GameScene.selectCell( thrower );
}
public void execute( Hero hero, String action ) {
curUser = hero;
curItem = this;
if (action.equals( AC_DROP )) {
doDrop( hero );
} else if (action.equals( AC_THROW )) {
doThrow( hero );
}
}
public void execute( Hero hero ) {
execute( hero, defaultAction );
}
protected void onThrow( int cell ) {
Heap heap = Dungeon.level.drop( this, cell );
if (!heap.isEmpty()) {
heap.sprite.drop( cell );
}
}
public boolean collect( Bag container ) {
ArrayList<Item> items = container.items;
if (items.contains( this )) {
return true;
}
for (Item item:items) {
if (item instanceof Bag && ((Bag)item).grab( this )) {
return collect( (Bag)item );
}
}
if (stackable) {
for (Item item:items) {
if (isSimilar( item )) {
item.quantity += quantity;
item.updateQuickslot();
return true;
}
}
}
if (items.size() < container.size) {
if (Dungeon.hero != null && Dungeon.hero.isAlive()) {
Badges.validateItemLevelAquired( this );
}
items.add( this );
QuickSlot.refresh();
Collections.sort( items, itemComparator );
return true;
} else {
GLog.n( TXT_PACK_FULL, name() );
return false;
}
}
public boolean collect() {
return collect( Dungeon.hero.belongings.backpack );
}
public Item detach( Bag container ) {
if (quantity <= 0) {
return null;
} else
if (quantity == 1) {
return detachAll( container );
} else {
quantity--;
updateQuickslot();
try {
return getClass().newInstance();
} catch (Exception e) {
return null;
}
}
}
public Item detachAll( Bag container ) {
for (Item item : container.items) {
if (item == this) {
container.items.remove( this );
QuickSlot.refresh();
return this;
} else if (item instanceof Bag) {
Bag bag = (Bag)item;
if (bag.contains( this )) {
detachAll( bag );
return this;
}
}
}
return this;
}
public boolean isSimilar( Item item ) {
return getClass() == item.getClass();
}
public Item upgrade() {
cursed = false;
cursedKnown = true;
this.level++;
return this;
}
public Item upgrade( int n ) {
for (int i=0; i < n; i++) {
upgrade();
}
return this;
}
public Item degrade() {
this.level--;
return this;
}
public Item degrade( int n ) {
for (int i=0; i < n; i++) {
degrade();
}
return this;
}
public int visiblyUpgraded() {
return levelKnown ? level : 0;
}
public boolean visiblyCursed() {
return cursed && cursedKnown;
}
public boolean isUpgradable() {
return true;
}
public boolean isIdentified() {
return levelKnown && cursedKnown;
}
public boolean isEquipped( Hero hero ) {
return false;
}
public Item identify() {
levelKnown = true;
cursedKnown = true;
return this;
}
public static void evoke( Hero hero ) {
hero.sprite.emitter().burst( Speck.factory( Speck.EVOKE ), 5 );
}
@Override
public String toString() {
if (levelKnown && level != 0) {
if (quantity > 1) {
return Utils.format( TXT_TO_STRING_LVL_X, name(), level, quantity );
} else {
return Utils.format( TXT_TO_STRING_LVL, name(), level );
}
} else {
if (quantity > 1) {
return Utils.format( TXT_TO_STRING_X, name(), quantity );
} else {
return Utils.format( TXT_TO_STRING, name() );
}
}
}
public String name() {
return name;
}
public final String trueName() {
return name;
}
public int image() {
return image;
}
public ItemSprite.Glowing glowing() {
return null;
}
public String info() {
return desc();
}
public String desc() {
return "";
}
public int quantity() {
return quantity;
}
public void quantity( int value ) {
quantity = value;
}
public int price() {
return 0;
}
public static Item virtual( Class<? extends Item> cl ) {
try {
Item item = (Item)cl.newInstance();
item.quantity = 0;
return item;
} catch (Exception e) {
return null;
}
}
public Item random() {
return this;
}
public String status() {
return quantity != 1 ? Integer.toString( quantity ) : null;
}
public void updateQuickslot() {
if ((stackable && Dungeon.quickslot == getClass()) || Dungeon.quickslot == this) {
QuickSlot.refresh();
}
}
private static final String QUANTITY = "quantity";
private static final String LEVEL = "level";
private static final String LEVEL_KNOWN = "levelKnown";
private static final String CURSED = "cursed";
private static final String CURSED_KNOWN = "cursedKnown";
private static final String QUICKSLOT = "quickslot";
@Override
public void storeInBundle( Bundle bundle ) {
bundle.put( QUANTITY, quantity );
bundle.put( LEVEL, level );
bundle.put( LEVEL_KNOWN, levelKnown );
bundle.put( CURSED, cursed );
bundle.put( CURSED_KNOWN, cursedKnown );
if (this == Dungeon.quickslot) {
bundle.put( QUICKSLOT, true );
}
}
@Override
public void restoreFromBundle( Bundle bundle ) {
quantity = bundle.getInt( QUANTITY );
levelKnown = bundle.getBoolean( LEVEL_KNOWN );
cursedKnown = bundle.getBoolean( CURSED_KNOWN );
int level = bundle.getInt( LEVEL );
if (level > 0) {
upgrade( level );
} else if (level < 0) {
degrade( -level );
}
cursed = bundle.getBoolean( CURSED );
if (bundle.getBoolean( QUICKSLOT )) {
Dungeon.quickslot = this;
}
}
public void cast( final Hero user, int dst ) {
final int cell = Ballistica.cast( user.pos, dst, false, true );
user.sprite.zap( cell );
user.busy();
Char enemy = Actor.findChar( cell );
QuickSlot.target( this, enemy );
float delay = TIME_TO_THROW;
if (this instanceof MissileWeapon) {
// Refactoring needed!
delay *= ((MissileWeapon)this).speedFactor( user );
if (enemy != null && enemy.buff( SnipersMark.class ) != null) {
delay *= 0.5f;
}
}
final float finalDelay = delay;
((MissileSprite)user.sprite.parent.recycle( MissileSprite.class )).
reset( user.pos, cell, this, new Callback() {
@Override
public void call() {
Item.this.detach( user.belongings.backpack ).onThrow( cell );
user.spendAndNext( finalDelay );
}
} );
}
protected static Hero curUser = null;
protected static Item curItem = null;
protected static CellSelector.Listener thrower = new CellSelector.Listener() {
@Override
public void onSelect( Integer target ) {
if (target != null) {
curItem.cast( curUser, target );
}
}
@Override
public String prompt() {
return "Choose direction of throw";
}
};
}
@@ -0,0 +1,162 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class ItemStatusHandler<T extends Item> {
private Class<? extends T>[] items;
private HashMap<Class<? extends T>, Integer> images;
private HashMap<Class<? extends T>, String> labels;
private HashSet<Class<? extends T>> known;
public ItemStatusHandler( Class<? extends T>[] items, String[] allLabels, Integer[] allImages ) {
this.items = items;
this.images = new HashMap<Class<? extends T>, Integer>();
this.labels = new HashMap<Class<? extends T>, String>();
known = new HashSet<Class<? extends T>>();
ArrayList<String> labelsLeft = new ArrayList<String>( Arrays.asList( allLabels ) );
ArrayList<Integer> imagesLeft = new ArrayList<Integer>( Arrays.asList( allImages ) );
for (int i=0; i < items.length; i++) {
Class<? extends T> item = (Class<? extends T>)(items[i]);
int index = Random.Int( labelsLeft.size() );
labels.put( item, labelsLeft.get( index ) );
labelsLeft.remove( index );
images.put( item, imagesLeft.get( index ) );
imagesLeft.remove( index );
}
}
public ItemStatusHandler( Class<? extends T>[] items, String[] labels, Integer[] images, Bundle bundle ) {
this.items = items;
this.images = new HashMap<Class<? extends T>, Integer>();
this.labels = new HashMap<Class<? extends T>, String>();
known = new HashSet<Class<? extends T>>();
restore( bundle, labels, images );
}
private static final String PFX_IMAGE = "_image";
private static final String PFX_LABEL = "_label";
private static final String PFX_KNOWN = "_known";
public void save( Bundle bundle ) {
for (int i=0; i < items.length; i++) {
String itemName = items[i].toString();
bundle.put( itemName + PFX_IMAGE, images.get( items[i] ) );
bundle.put( itemName + PFX_LABEL, labels.get( items[i] ) );
bundle.put( itemName + PFX_KNOWN, known.contains( items[i] ) );
}
}
private void restore( Bundle bundle, String[] allLabels, Integer[] allImages ) {
ArrayList<String> labelsLeft = new ArrayList<String>( Arrays.asList( allLabels ) );
ArrayList<Integer> imagesLeft = new ArrayList<Integer>( Arrays.asList( allImages ) );
for (int i=0; i < items.length; i++) {
Class<? extends T> item = (Class<? extends T>)(items[i]);
String itemName = item.toString();
if (bundle.contains( itemName + PFX_LABEL )) {
String label = bundle.getString( itemName + PFX_LABEL );
labels.put( item, label );
labelsLeft.remove( label );
Integer image = bundle.getInt( itemName + PFX_IMAGE );
images.put( item, image );
imagesLeft.remove( image );
if (bundle.getBoolean( itemName + PFX_KNOWN )) {
known.add( item );
}
} else {
int index = Random.Int( labelsLeft.size() );
labels.put( item, labelsLeft.get( index ) );
labelsLeft.remove( index );
images.put( item, imagesLeft.get( index ) );
imagesLeft.remove( index );
}
}
}
public int image( T item ) {
return images.get( item.getClass() );
}
public String label( T item ) {
return labels.get( item.getClass() );
}
public boolean isKnown( T item ) {
return known.contains( item.getClass() );
}
@SuppressWarnings("unchecked")
public void know( T item ) {
known.add( (Class<? extends T>)item.getClass() );
if (known.size() == items.length - 1) {
for (int i=0; i < items.length; i++) {
if (!known.contains( items[i] )) {
known.add( items[i] );
break;
}
}
}
}
public HashSet<Class<? extends T>> known() {
return known;
}
public HashSet<Class<? extends T>> unknown() {
HashSet<Class<? extends T>> result = new HashSet<Class<? extends T>>();
for (Class<? extends T> i : items) {
if (!known.contains( i )) {
result.add( i );
}
}
return result;
}
}
@@ -0,0 +1,115 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlot;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Random;
public class KindOfWeapon extends EquipableItem {
private static final String TXT_EQUIP_CURSED = "you wince as your grip involuntarily tightens around your %s";
private static final String TXT_UNEQUIP_CURSED = "you can't remove cursed %s!";
protected static final float TIME_TO_EQUIP = 1f;
public int MIN = 0;
public int MAX = 1;
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( isEquipped( hero ) ? AC_UNEQUIP : AC_EQUIP );
return actions;
}
@Override
public boolean isEquipped( Hero hero ) {
return hero.belongings.weapon == this;
}
@Override
public boolean doEquip( Hero hero ) {
detachAll( hero.belongings.backpack );
if (hero.belongings.weapon == null || hero.belongings.weapon.doUnequip( hero, true )) {
hero.belongings.weapon = this;
activate( hero );
QuickSlot.refresh();
cursedKnown = true;
if (cursed) {
equipCursed( hero );
GLog.n( TXT_EQUIP_CURSED, name() );
}
hero.spendAndNext( TIME_TO_EQUIP );
return true;
} else {
collect( hero.belongings.backpack );
return false;
}
}
@Override
public boolean doUnequip( Hero hero, boolean collect ) {
if (cursed) {
GLog.w( TXT_UNEQUIP_CURSED, name() );
return false;
}
hero.belongings.weapon = null;
hero.spendAndNext( TIME_TO_EQUIP );
if (collect && !collect( hero.belongings.backpack )) {
Dungeon.level.drop( this, hero.pos );
}
return true;
}
public void activate( Hero hero ) {
}
public int damageRoll( Hero owner ) {
return Random.NormalIntRange( MIN, MAX );
}
public float acuracyFactor( Hero hero ) {
return 1f;
}
public float speedFactor( Hero hero ) {
return 1f;
}
public void proc( Char attacker, Char defender, int damage ) {
}
}
@@ -0,0 +1,178 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.scenes.InterlevelScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.watabou.utils.Bundle;
public class LloydsBeacon extends Item {
private static final String TXT_PREVENTING =
"Strong magic aura of this place prevents you from using the lloyd's beacon!";
private static final String TXT_CREATURES =
"Psychic aura of neighbouring creatures doesn't allow you to use the lloyd's beacon at this moment.";
private static final String TXT_RETURN =
"The lloyd's beacon is successfully set at your current location, now you can return here anytime.";
private static final String TXT_INFO =
"Lloyd's beacon is an intricate magic device, that allows you to return to a place you have already been.";
private static final String TXT_SET =
"\n\nThis beacon was set somewhere on the level %d of Pixel Dungeon.";
public static final float TIME_TO_USE = 1;
public static final String AC_SET = "SET";
public static final String AC_RETURN = "RETURN";
private int returnDepth = -1;
private int returnPos;
{
name = "lloyd's beacon";
image = ItemSpriteSheet.BEACON;
unique = true;
}
private static final String DEPTH = "depth";
private static final String POS = "pos";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( DEPTH, returnDepth );
if (returnDepth != -1) {
bundle.put( POS, returnPos );
}
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle(bundle);
returnDepth = bundle.getInt( DEPTH );
returnPos = bundle.getInt( POS );
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_SET );
if (returnDepth != -1) {
actions.add( AC_RETURN );
}
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action == AC_SET || action == AC_RETURN) {
if (Dungeon.bossLevel()) {
hero.spend( LloydsBeacon.TIME_TO_USE );
GLog.w( TXT_PREVENTING );
return;
}
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
if (Actor.findChar( hero.pos + Level.NEIGHBOURS8[i] ) != null) {
GLog.w( TXT_CREATURES );
return;
}
}
}
if (action == AC_SET) {
returnDepth = Dungeon.depth;
returnPos = hero.pos;
hero.spend( LloydsBeacon.TIME_TO_USE );
hero.busy();
hero.sprite.operate( hero.pos );
Sample.INSTANCE.play( Assets.SND_BEACON );
GLog.i( TXT_RETURN );
} else if (action == AC_RETURN) {
if (returnDepth == Dungeon.depth) {
reset();
WandOfBlink.appear( hero, returnPos );
Dungeon.level.press( returnPos, hero );
Dungeon.observe();
} else {
InterlevelScene.mode = InterlevelScene.Mode.RETURN;
InterlevelScene.returnDepth = returnDepth;
InterlevelScene.returnPos = returnPos;
reset();
Game.switchScene( InterlevelScene.class );
}
} else {
super.execute( hero, action );
}
}
public void reset() {
returnDepth = -1;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
private static final Glowing WHITE = new Glowing( 0xFFFFFF );
@Override
public Glowing glowing() {
return returnDepth != -1 ? WHITE : null;
}
@Override
public String info() {
return TXT_INFO + (returnDepth == -1 ? "" : Utils.format( TXT_SET, returnDepth ) );
}
}
@@ -0,0 +1,122 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PurpleParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
public class Stylus extends Item {
private static final String TXT_SELECT_ARMOR = "Select an armor to inscribe on";
private static final String TXT_INSCRIBED = "you inscribed the %s on your %s";
private static final float TIME_TO_INSCRIBE = 2;
private static final String AC_INSCRIBE = "INSCRIBE";
{
name = "arcane stylus";
image = ItemSpriteSheet.STYLUS;
stackable = true;
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_INSCRIBE );
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action == AC_INSCRIBE) {
curUser = hero;
GameScene.selectItem( itemSelector, WndBag.Mode.ARMOR, TXT_SELECT_ARMOR );
} else {
super.execute( hero, action );
}
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
private void inscribe( Armor armor ) {
detach( curUser.belongings.backpack );
Class<? extends Armor.Glyph> oldGlyphClass = armor.glyph != null ? armor.glyph.getClass() : null;
Armor.Glyph glyph = Armor.Glyph.random();
while (glyph.getClass() == oldGlyphClass) {
glyph = Armor.Glyph.random();
}
GLog.w( TXT_INSCRIBED, glyph.name(), armor.name() );
armor.inscribe( glyph );
curUser.sprite.operate( curUser.pos );
curUser.sprite.centerEmitter().start( PurpleParticle.BURST, 0.05f, 10 );
Sample.INSTANCE.play( Assets.SND_BURNING );
curUser.spend( TIME_TO_INSCRIBE );
curUser.busy();
}
@Override
public int price() {
return 50 * quantity;
}
@Override
public String info() {
return
"This arcane stylus is made of some dark, very hard stone. Using it you can inscribe " +
"a magical glyph on your armor, but you have no power over choosing what glyph it will be, " +
"the stylus will decide it for you.";
}
private final WndBag.Listener itemSelector = new WndBag.Listener() {
@Override
public void onSelect( Item item ) {
if (item != null) {
Stylus.this.inscribe( (Armor)item );
}
}
};
}
@@ -0,0 +1,145 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Fury;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.SpellSprite;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndChooseWay;
public class TomeOfMastery extends Item {
private static final String TXT_BLINDED = "You can't read while blinded";
public static final float TIME_TO_READ = 10;
public static final String AC_READ = "READ";
{
stackable = false;
name = "Tome of Mastery";
image = ItemSpriteSheet.MASTERY;
unique = true;
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_READ );
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action.equals( AC_READ )) {
if (hero.buff( Blindness.class ) != null) {
GLog.w( TXT_BLINDED );
return;
}
curUser = hero;
HeroSubClass way1 = null;
HeroSubClass way2 = null;
switch (hero.heroClass) {
case WARRIOR:
way1 = HeroSubClass.GLADIATOR;
way2 = HeroSubClass.BERSERKER;
break;
case MAGE:
way1 = HeroSubClass.BATTLEMAGE;
way2 = HeroSubClass.WARLOCK;
break;
case ROGUE:
way1 = HeroSubClass.FREERUNNER;
way2 = HeroSubClass.ASSASSIN;
break;
case HUNTRESS:
way1 = HeroSubClass.SNIPER;
way2 = HeroSubClass.WARDEN;
break;
}
GameScene.show( new WndChooseWay( this, way1, way2 ) );
} else {
super.execute( hero, action );
}
}
@Override
public boolean doPickUp( Hero hero ) {
Badges.validateMastery();
return super.doPickUp( hero );
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public String info() {
return
"This worn leather book is not that thick, but you feel somehow, " +
"that you can gather a lot from it. Remember though that reading " +
"this tome may require some time.";
}
public void choose( HeroSubClass way ) {
detach( curUser.belongings.backpack );
curUser.spend( TomeOfMastery.TIME_TO_READ );
curUser.busy();
curUser.subClass = way;
curUser.sprite.operate( curUser.pos );
Sample.INSTANCE.play( Assets.SND_MASTERY );
SpellSprite.show( curUser, SpellSprite.MASTERY );
curUser.sprite.emitter().burst( Speck.factory( Speck.MASTERY ), 12 );
GLog.w( "You have chosen the way of the %s!", Utils.capitalize( way.title() ) );
if (way == HeroSubClass.BERSERKER && curUser.HP <= curUser.HT * Fury.LEVEL) {
Buff.affect( curUser, Fury.class );
}
}
}
@@ -0,0 +1,94 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items;
import java.util.ArrayList;
import com.watabou.noosa.particles.Emitter;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class Torch extends Item {
public static final String AC_LIGHT = "LIGHT";
public static final float TIME_TO_LIGHT = 1;
{
name = "torch";
image = ItemSpriteSheet.TORCH;
stackable = true;
defaultAction = AC_LIGHT;
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_LIGHT );
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action == AC_LIGHT) {
hero.spend( TIME_TO_LIGHT );
hero.busy();
hero.sprite.operate( hero.pos );
detach( hero.belongings.backpack );
Buff.affect( hero, Light.class, Light.DURATION );
Emitter emitter = hero.sprite.centerEmitter();
emitter.start( FlameParticle.FACTORY, 0.2f, 3 );
} else {
super.execute( hero, action );
}
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public int price() {
return 10 * quantity;
}
@Override
public String info() {
return
"It's an indispensable item in The Demon Halls, which are notorious for their poor ambient lighting.";
}
}
@@ -0,0 +1,376 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import java.util.ArrayList;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.*;
import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.watabou.utils.Bundlable;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class Armor extends EquipableItem {
private static final String TXT_EQUIP_CURSED = "your %s constricts around you painfully";
private static final String TXT_UNEQUIP_CURSED = "You can't remove cursed %s!";
private static final String TXT_IDENTIFY = "you are now familiar enough with your %s to identify it. It is %s.";
private static final String TXT_TO_STRING = "%s :%d";
private static final String TXT_INCOMPATIBLE =
"Interaction of different types of magic has erased the glyph on this armor!";
public int tier;
public int STR;
public int DR;
private int hitsToKnow = 10;
public Glyph glyph;
public Armor( int tier ) {
this.tier = tier;
STR = typicalSTR();
DR = typicalDR();
}
private static final String GLYPH = "glyph";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( GLYPH, glyph );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
glyph = (Glyph)bundle.get( GLYPH );
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( isEquipped( hero ) ? AC_UNEQUIP : AC_EQUIP );
return actions;
}
@Override
public boolean doEquip( Hero hero ) {
detach( hero.belongings.backpack );
if (hero.belongings.armor == null || hero.belongings.armor.doUnequip( hero, true )) {
hero.belongings.armor = this;
cursedKnown = true;
if (cursed) {
equipCursed( hero );
GLog.n( TXT_EQUIP_CURSED, toString() );
}
((HeroSprite)hero.sprite).updateArmor();
hero.spendAndNext( 2 * hero.speed() );
return true;
} else {
collect( hero.belongings.backpack );
return false;
}
}
@Override
public boolean doUnequip( Hero hero, boolean collect ) {
if (cursed) {
GLog.w( TXT_UNEQUIP_CURSED, name() );
return false;
} else {
hero.belongings.armor = null;
hero.spendAndNext( hero.speed() );
((HeroSprite)hero.sprite).updateArmor();
if (collect && !collect( hero.belongings.backpack )) {
Dungeon.level.drop( this, hero.pos );
}
return true;
}
}
@Override
public boolean isEquipped( Hero hero ) {
return hero.belongings.armor == this;
}
@Override
public Item upgrade() {
return upgrade( false );
}
public Item upgrade( boolean inscribe ) {
if (glyph != null) {
if (!inscribe && Random.Int( level ) > 0) {
GLog.w( TXT_INCOMPATIBLE );
inscribe( null );
}
} else {
if (inscribe) {
inscribe( Glyph.random() );
}
};
DR += tier;
STR--;
return super.upgrade();
}
public Item safeUpgrade() {
return upgrade( glyph != null );
}
@Override
public Item degrade() {
DR -= tier;
STR++;
return super.degrade();
}
public int proc( Char attacker, Char defender, int damage ) {
if (glyph != null) {
damage = glyph.proc( this, attacker, defender, damage );
}
if (!levelKnown) {
if (--hitsToKnow <= 0) {
levelKnown = true;
GLog.w( TXT_IDENTIFY, name(), toString() );
Badges.validateItemLevelAquired( this );
}
}
return damage;
}
@Override
public String toString() {
return levelKnown ? Utils.format( TXT_TO_STRING, super.toString(), STR ) : super.toString();
}
@Override
public String name() {
return glyph == null ? super.name() : glyph.name( super.name() );
}
@Override
public String info() {
String name = name();
StringBuilder info = new StringBuilder( desc() );
if (levelKnown) {
info.append(
"\n\nThis " + name + " provides damage absorption up to " +
"" + Math.max( DR, 0 ) + " points per attack. " );
if (STR > Dungeon.hero.STR()) {
if (isEquipped( Dungeon.hero )) {
info.append(
"\n\nBecause of your inadequate strength your " +
"movement speed and defense skill is decreased. " );
} else {
info.append(
"\n\nBecause of your inadequate strength wearing this armor " +
"will decrease your movement speed and defense skill. " );
}
}
} else {
info.append(
"\n\nTypical " + name + " provides damage absorption up to " + typicalDR() + " points per attack " +
" and requires " + typicalSTR() + " points of strength. " );
if (typicalSTR() > Dungeon.hero.STR()) {
info.append( "Probably this armor is too heavy for you. " );
}
}
if (glyph != null) {
info.append( "It is inscribed." );
}
if (isEquipped( Dungeon.hero )) {
info.append( "\n\nYou are wearing the " + name +
(cursed ? ", and because it is cursed, you are powerless to remove it." : ".") );
} else {
if (cursedKnown && cursed) {
info.append( "\n\nYou can feel a malevolent magic lurking within the " + name + "." );
}
}
return info.toString();
}
@Override
public Item random() {
if (Random.Float() < 0.4) {
int n = 1;
if (Random.Int( 3 ) == 0) {
n++;
if (Random.Int( 3 ) == 0) {
n++;
}
}
if (Random.Int( 2 ) == 0) {
upgrade( n );
} else {
degrade( n );
cursed = true;
}
}
if (Random.Int( 10 ) == 0) {
inscribe( Glyph.random() );
}
return this;
}
public int typicalSTR() {
return 7 + tier * 2;
}
public int typicalDR() {
return tier * 2;
}
@Override
public int price() {
int price = 10 * (1 << (tier - 1));
if (glyph != null) {
price *= 1.5;
}
if (cursed && cursedKnown) {
price /= 2;
}
if (levelKnown) {
if (level > 0) {
price *= (level + 1);
} else if (level < 0) {
price /= (1 - level);
}
}
if (price < 1) {
price = 1;
}
return price;
}
public Armor inscribe( Glyph glyph ) {
this.glyph = glyph;
return this;
}
public boolean isInscribed() {
return glyph != null;
}
@Override
public ItemSprite.Glowing glowing() {
return glyph != null ? glyph.glowing() : null;
}
public static abstract class Glyph implements Bundlable {
private static final Class<?>[] glyphs = new Class<?>[]{
Bounce.class, Affection.class, AntiEntropy.class, Multiplicity.class,
Potential.class, Metabolism.class, Stench.class, Viscosity.class,
Displacement.class, Entanglement.class };
private static final float[] chances= new float[]{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
public abstract int proc( Armor armor, Char attacker, Char defender, int damage );
public String name() {
return name( "glyph" );
}
public String name( String armorName ) {
return armorName;
}
@Override
public void restoreFromBundle( Bundle bundle ) {
}
@Override
public void storeInBundle( Bundle bundle ) {
}
public ItemSprite.Glowing glowing() {
return ItemSprite.Glowing.WHITE;
}
public boolean checkOwner( Char owner ) {
if (!owner.isAlive() && owner instanceof Hero) {
((Hero)owner).killerGlyph = this;
Badges.validateDeathFromGlyph();
return true;
} else {
return false;
}
}
@SuppressWarnings("unchecked")
public static Glyph random() {
try {
return ((Class<Glyph>)glyphs[ Random.chances( chances ) ]).newInstance();
} catch (Exception e) {
return null;
}
}
}
}
@@ -0,0 +1,134 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import java.util.ArrayList;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
abstract public class ClassArmor extends Armor {
private static final String TXT_LOW_HEALTH = "Your health is too low!";
private static final String TXT_NOT_EQUIPPED = "You need to be wearing this armor to use its special power!";
{
levelKnown = true;
cursedKnown = true;
defaultAction = special();
}
public ClassArmor() {
super( 6 );
}
public static ClassArmor upgrade ( Hero owner, Armor armor ) {
ClassArmor classArmor = null;
switch (owner.heroClass) {
case WARRIOR:
classArmor = new WarriorArmor();
break;
case ROGUE:
classArmor = new RogueArmor();
break;
case MAGE:
classArmor = new MageArmor();
break;
case HUNTRESS:
classArmor = new HuntressArmor();
break;
}
classArmor.STR = armor.STR;
classArmor.DR = armor.DR;
classArmor.inscribe( armor.glyph );
return classArmor;
}
private static final String ARMOR_STR = "STR";
private static final String ARMOR_DR = "DR";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( ARMOR_STR, STR );
bundle.put( ARMOR_DR, DR );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
STR = bundle.getInt( ARMOR_STR );
DR = bundle.getInt( ARMOR_DR );
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
if (hero.HP >= 2 && isEquipped( hero )) {
actions.add( special() );
}
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action == special()) {
if (hero.HP < 2) {
GLog.w( TXT_LOW_HEALTH );
} else if (!isEquipped( hero )) {
GLog.w( TXT_NOT_EQUIPPED );
} else {
curUser = hero;
doSpecial();
}
} else {
super.execute( hero, action );
}
}
abstract public String special();
abstract public void doSpecial();
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public int price() {
return 0;
}
@Override
public String desc() {
return "The thing looks awesome!";
}
}
@@ -0,0 +1,38 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class ClothArmor extends Armor {
{
name = "cloth armor";
image = ItemSpriteSheet.ARMOR_CLOTH;
}
public ClothArmor() {
super( 1 );
}
@Override
public String desc() {
return "This lightweight armor offers basic protection.";
}
}
@@ -0,0 +1,107 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import java.util.HashMap;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Shuriken;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.sprites.MissileSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Callback;
public class HuntressArmor extends ClassArmor {
private static final String TXT_NO_ENEMIES = "No enemies in sight";
private static final String TXT_NOT_HUNTRESS = "Only huntresses can use this armor!";
private static final String AC_SPECIAL = "SPECTRAL BLADES";
{
name = "huntress cloak";
image = ItemSpriteSheet.ARMOR_HUNTRESS;
}
private HashMap<Callback, Mob> targets = new HashMap<Callback, Mob>();
@Override
public String special() {
return AC_SPECIAL;
}
@Override
public void doSpecial() {
Item proto = new Shuriken();
for (Mob mob : Dungeon.level.mobs) {
if (Level.fieldOfView[mob.pos]) {
Callback callback = new Callback() {
@Override
public void call() {
curUser.attack( targets.get( this ) );
targets.remove( this );
if (targets.isEmpty()) {
curUser.spendAndNext( curUser.attackDelay() );
}
}
};
((MissileSprite)curUser.sprite.parent.recycle( MissileSprite.class )).
reset( curUser.pos, mob.pos, proto, callback );
targets.put( callback, mob );
}
}
if (targets.size() == 0) {
GLog.w( TXT_NO_ENEMIES );
return;
}
curUser.HP /= 2;
curUser.sprite.zap( curUser.pos );
curUser.busy();
}
@Override
public boolean doEquip( Hero hero ) {
if (hero.heroClass == HeroClass.HUNTRESS) {
return super.doEquip( hero );
} else {
GLog.w( TXT_NOT_HUNTRESS );
return false;
}
}
@Override
public String desc() {
return
"A huntress in such cloak can create a fan of spectral blades. Each of these blades " +
"will target a single enemy in the huntress's field of view, inflicting damage depending " +
"on her currently equipped melee weapon.";
}
}
@@ -0,0 +1,38 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class LeatherArmor extends Armor {
{
name = "leather armor";
image = ItemSpriteSheet.ARMOR_LEATHER;
}
public LeatherArmor() {
super( 2 );
}
@Override
public String desc() {
return "Armor made from tanned monster hide. Not as light as cloth armor but provides better protection.";
}
}
@@ -0,0 +1,87 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class MageArmor extends ClassArmor {
private static final String AC_SPECIAL = "MOLTEN EARTH";
private static final String TXT_NOT_MAGE = "Only mages can use this armor!";
{
name = "mage robe";
image = ItemSpriteSheet.ARMOR_MAGE;
}
@Override
public String special() {
return AC_SPECIAL;
}
@Override
public String desc() {
return
"Wearing this gorgeous robe, a mage can cast a spell of molten earth: all the enemies " +
"in his field of view will be set on fire and unable to move at the same time.";
}
@Override
public void doSpecial() {
for (Mob mob : Dungeon.level.mobs) {
if (Level.fieldOfView[mob.pos]) {
Buff.affect( mob, Burning.class ).reignite( mob );
Buff.prolong( mob, Roots.class, 3 );
}
}
curUser.HP /= 2;
curUser.spend( Actor.TICK );
curUser.sprite.operate( curUser.pos );
curUser.busy();
curUser.sprite.centerEmitter().start( ElmoParticle.FACTORY, 0.15f, 4 );
Sample.INSTANCE.play( Assets.SND_READ );
}
@Override
public boolean doEquip( Hero hero ) {
if (hero.heroClass == HeroClass.MAGE) {
return super.doEquip( hero );
} else {
GLog.w( TXT_NOT_MAGE );
return false;
}
}
}
@@ -0,0 +1,39 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class MailArmor extends Armor {
{
name = "mail armor";
image = ItemSpriteSheet.ARMOR_MAIL;
}
public MailArmor() {
super( 3 );
}
@Override
public String desc() {
return
"Interlocking metal links make for a tough but flexible suit of armor.";
}
}
@@ -0,0 +1,40 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class PlateArmor extends Armor {
{
name = "plate armor";
image = ItemSpriteSheet.ARMOR_PLATE;
}
public PlateArmor() {
super( 5 );
}
@Override
public String desc() {
return
"Enormous plates of metal are joined together into a suit that provides " +
"unmatched protection to any adventurer strong enough to bear its staggering weight.";
}
}
@@ -0,0 +1,117 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob.State;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class RogueArmor extends ClassArmor {
private static final String TXT_FOV = "You can only jump to an empty location in your field of view";
private static final String TXT_NOT_ROGUE = "Only rogues can use this armor!";
private static final String AC_SPECIAL = "SMOKE BOMB";
{
name = "rogue garb";
image = ItemSpriteSheet.ARMOR_ROGUE;
}
@Override
public String special() {
return AC_SPECIAL;
}
@Override
public void doSpecial() {
GameScene.selectCell( teleporter );
}
@Override
public boolean doEquip( Hero hero ) {
if (hero.heroClass == HeroClass.ROGUE) {
return super.doEquip( hero );
} else {
GLog.w( TXT_NOT_ROGUE );
return false;
}
}
@Override
public String desc() {
return
"Wearing this dark garb, a rogue can perform a trick, that is called \"smoke bomb\" " +
"(though no real explosives are used): he blinds enemies who could see him and jumps aside.";
}
protected static CellSelector.Listener teleporter = new CellSelector.Listener() {
@Override
public void onSelect( Integer target ) {
if (target != null) {
if (!Level.fieldOfView[target] ||
!(Level.passable[target] || Level.avoid[target]) ||
Actor.findChar( target ) != null) {
GLog.w( TXT_FOV );
return;
}
curUser.HP /= 2;
for (Mob mob : Dungeon.level.mobs) {
if (Level.fieldOfView[mob.pos]) {
Buff.prolong( mob, Blindness.class, 2 );
mob.state = State.WANDERING;
mob.sprite.emitter().burst( Speck.factory( Speck.LIGHT ), 4 );
}
}
WandOfBlink.appear( curUser, target );
CellEmitter.get( target ).burst( Speck.factory( Speck.WOOL ), 10 );
Sample.INSTANCE.play( Assets.SND_PUFF );
Dungeon.level.press( target, curUser );
Dungeon.observe();
curUser.spendAndNext( Actor.TICK );
}
}
@Override
public String prompt() {
return "Choose a location to jump to";
}
};
}
@@ -0,0 +1,39 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class ScaleArmor extends Armor {
{
name = "scale armor";
image = ItemSpriteSheet.ARMOR_SCALE;
}
public ScaleArmor() {
super( 4 );
}
@Override
public String desc() {
return
"The metal scales sewn onto a leather vest create a flexible, yet protective armor.";
}
}
@@ -0,0 +1,129 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor;
import com.watabou.noosa.Camera;
import com.watabou.noosa.tweeners.PosTweener;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Fury;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.PointF;
public class WarriorArmor extends ClassArmor {
private static int LEAP_TIME = 1;
private static int SHOCK_TIME = 3;
private static final String AC_SPECIAL = "HEROIC LEAP";
private static final String TXT_NOT_WARRIOR = "Only warriors can use this armor!";
{
name = "warrior suit of armor";
image = ItemSpriteSheet.ARMOR_WARRIOR;
}
@Override
public String special() {
return AC_SPECIAL;
}
@Override
public void doSpecial() {
GameScene.selectCell( leaper );
}
@Override
public boolean doEquip( Hero hero ) {
if (hero.heroClass == HeroClass.WARRIOR) {
return super.doEquip( hero );
} else {
GLog.w( TXT_NOT_WARRIOR );
return false;
}
}
@Override
public String desc() {
return
"While this armor looks heavy, it allows a warrior to perform heroic leap towards " +
"a targeted location, slamming down to stun all neighbouring enemies.";
}
protected static CellSelector.Listener leaper = new CellSelector.Listener() {
@Override
public void onSelect( Integer target ) {
if (target != null && target != curUser.pos) {
int cell = Ballistica.cast( curUser.pos, target, false, true );
if (Actor.findChar( cell ) != null && cell != curUser.pos) {
cell = Ballistica.trace[Ballistica.distance - 2];
}
curUser.HP /= 2;
if (curUser.subClass == HeroSubClass.BERSERKER && curUser.HP <= curUser.HT * Fury.LEVEL) {
Buff.affect( curUser, Fury.class );
}
Invisibility.dispel();
curUser.move( cell );
curUser.sprite.place( cell );
Dungeon.level.press( target, curUser );
Dungeon.observe();
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
Char mob = Actor.findChar( curUser.pos + Level.NEIGHBOURS8[i] );
if (mob != null && mob != curUser) {
Buff.prolong( mob, Paralysis.class, SHOCK_TIME );
}
}
PointF pos = curUser.sprite.point();
Camera.main.target = null;
curUser.sprite.y -= 16;
curUser.sprite.parent.add( new PosTweener( curUser.sprite, pos, 0.1f ) );
CellEmitter.center( cell ).burst( Speck.factory( Speck.DUST ), 10 );
curUser.spendAndNext( LEAP_TIME );
}
}
@Override
public String prompt() {
return "Choose direction to leap";
}
};
}
@@ -0,0 +1,66 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.utils.GameMath;
import com.watabou.utils.Random;
public class Affection extends Glyph {
private static final String TXT_AFFECTION = "%s of affection";
private static ItemSprite.Glowing PINK = new ItemSprite.Glowing( 0xFF4488 );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = (int)GameMath.gate( 0, armor.level, 6 );
if (Level.adjacent( attacker.pos, defender.pos ) && Random.Int( level / 2 + 5 ) >= 4) {
int duration = Random.IntRange( 2, 5 );
Buff.affect( attacker, Charm.class, Charm.durationFactor( attacker ) * duration );
attacker.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
Buff.affect( defender, Charm.class, Random.Float( Charm.durationFactor( defender ) * duration / 2, duration ) );
defender.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_AFFECTION, weaponName );
}
@Override
public Glowing glowing() {
return PINK;
}
}
@@ -0,0 +1,67 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SnowParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.utils.Random;
public class AntiEntropy extends Glyph {
private static final String TXT_ANTI_ENTROPY = "%s of anti-entropy";
private static ItemSprite.Glowing BLUE = new ItemSprite.Glowing( 0x0000FF );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level );
if (Level.adjacent( attacker.pos, defender.pos ) && Random.Int( level + 6 ) >= 5) {
Buff.prolong( attacker, Frost.class, Frost.duration( attacker ) * Random.Float( 1f, 1.5f ));
CellEmitter.get( attacker.pos ).start( SnowParticle.FACTORY, 0.2f, 6 );
Buff.affect( defender, Burning.class ).reignite( defender );
defender.sprite.emitter().burst( FlameParticle.FACTORY, 5 );
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_ANTI_ENTROPY, weaponName );
}
@Override
public Glowing glowing() {
return BLUE;
}
}
@@ -0,0 +1,72 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.watabou.utils.Random;
public class Bounce extends Glyph {
private static final String TXT_BOUNCE = "%s of bounce";
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level );
if (Level.adjacent( attacker.pos, defender.pos ) && Random.Int( level + 5) >= 4) {
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
int ofs = Level.NEIGHBOURS8[i];
if (attacker.pos - defender.pos == ofs) {
int newPos = attacker.pos + ofs;
if ((Level.passable[newPos] || Level.avoid[newPos]) && Actor.findChar( newPos ) == null) {
Actor.addDelayed( new Pushing( attacker, attacker.pos, newPos ), -1 );
attacker.pos = newPos;
// :(
if (attacker instanceof Mob) {
Dungeon.level.mobPress( (Mob)attacker );
} else {
Dungeon.level.press( newPos, attacker );
}
}
break;
}
}
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_BOUNCE, weaponName );
}
}
@@ -0,0 +1,69 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.utils.Random;
public class Displacement extends Glyph {
private static final String TXT_DISPLACEMENT = "%s of displacement";
private static ItemSprite.Glowing BLUE = new ItemSprite.Glowing( 0x66AAFF );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage ) {
if (Dungeon.bossLevel()) {
return damage;
}
int nTries = (armor.level < 0 ? 1 : armor.level + 1) * 5;
for (int i=0; i < nTries; i++) {
int pos = Random.Int( Level.LENGTH );
if (Dungeon.visible[pos] && Level.passable[pos] && Actor.findChar( pos ) == null) {
WandOfBlink.appear( defender, pos );
Dungeon.level.press( pos, defender );
Dungeon.observe();
break;
}
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_DISPLACEMENT, weaponName );
}
@Override
public Glowing glowing() {
return BLUE;
}
}
@@ -0,0 +1,66 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.watabou.noosa.Camera;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.EarthParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.plants.Earthroot;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.utils.Random;
public class Entanglement extends Glyph {
private static final String TXT_ENTANGLEMENT = "%s of entanglement";
private static ItemSprite.Glowing GREEN = new ItemSprite.Glowing( 0x448822 );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage ) {
int level = Math.max( 0, armor.level );
if (Random.Int( 4 ) == 0) {
Buff.prolong( defender, Roots.class, 5 - level / 5 );
Buff.affect( defender, Earthroot.Armor.class ).level( 5 * (level + 1) );
CellEmitter.bottom( defender.pos ).start( EarthParticle.FACTORY, 0.05f, 8 );
Camera.main.shake( 1, 0.4f );
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_ENTANGLEMENT, weaponName );
}
@Override
public Glowing glowing() {
return GREEN;
}
}
@@ -0,0 +1,74 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.watabou.utils.Random;
public class Metabolism extends Glyph {
private static final String TXT_METABOLISM = "%s of metabolism";
private static ItemSprite.Glowing RED = new ItemSprite.Glowing( 0xCC0000 );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level );
if (Random.Int( level / 2 + 5 ) >= 4) {
int healing = Math.min( defender.HT - defender.HP, Random.Int( 1, defender.HT / 5 ) );
if (healing > 0) {
Hunger hunger = defender.buff( Hunger.class );
if (hunger != null && !hunger.isStarving()) {
hunger.satisfy( -Hunger.STARVING / 10 );
BuffIndicator.refreshHero();
defender.HP += healing;
defender.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 );
defender.sprite.showStatus( CharSprite.POSITIVE, Integer.toString( healing ) );
}
}
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_METABOLISM, weaponName );
}
@Override
public Glowing glowing() {
return RED;
}
}
@@ -0,0 +1,81 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import java.util.ArrayList;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.MirrorImage;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.utils.Random;
public class Multiplicity extends Glyph {
private static final String TXT_MULTIPLICITY = "%s of multiplicity";
private static ItemSprite.Glowing PINK = new ItemSprite.Glowing( 0xCCAA88 );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level );
if (Random.Int( level / 2 + 6 ) >= 5) {
ArrayList<Integer> respawnPoints = new ArrayList<Integer>();
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
int p = defender.pos + Level.NEIGHBOURS8[i];
if (Actor.findChar( p ) == null && (Level.passable[p] || Level.avoid[p])) {
respawnPoints.add( p );
}
}
if (respawnPoints.size() > 0) {
MirrorImage mob = new MirrorImage();
mob.duplicate( (Hero)defender );
GameScene.add( mob );
WandOfBlink.appear( mob, Random.element( respawnPoints ) );
defender.damage( Random.IntRange( 1, defender.HT / 6 ), /*attacker*/ this );
checkOwner( defender );
}
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_MULTIPLICITY, weaponName );
}
@Override
public Glowing glowing() {
return PINK;
}
}
@@ -0,0 +1,72 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.watabou.noosa.Camera;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.effects.Lightning;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.LightningTrap;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.utils.Random;
public class Potential extends Glyph {
private static final String TXT_POTENTIAL = "%s of potential";
private static ItemSprite.Glowing BLUE = new ItemSprite.Glowing( 0x66CCEE );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level );
if (Level.adjacent( attacker.pos, defender.pos ) && Random.Int( level + 7 ) >= 6) {
int dmg = Random.IntRange( 1, damage );
attacker.damage( dmg, LightningTrap.LIGHTNING );
dmg = Random.IntRange( 1, dmg );
defender.damage( dmg, LightningTrap.LIGHTNING );
checkOwner( defender );
if (defender == Dungeon.hero) {
Camera.main.shake( 2, 0.3f );
}
int[] points = {attacker.pos, defender.pos};
attacker.sprite.parent.add( new Lightning( points, 2, null ) );
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_POTENTIAL, weaponName );
}
@Override
public Glowing glowing() {
return BLUE;
}
}
@@ -0,0 +1,61 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.watabou.utils.Random;
public class Stench extends Glyph {
private static final String TXT_STENCH = "%s of stench";
private static ItemSprite.Glowing GREEN = new ItemSprite.Glowing( 0x22CC44 );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage) {
int level = Math.max( 0, armor.level );
if (Level.adjacent( attacker.pos, defender.pos ) && Random.Int( level + 5 ) >= 4) {
GameScene.add( Blob.seed( attacker.pos, 20, ToxicGas.class ) );
}
return damage;
}
@Override
public String name( String weaponName) {
return String.format( TXT_STENCH, weaponName );
}
@Override
public Glowing glowing() {
return GREEN;
}
}
@@ -0,0 +1,150 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor.Glyph;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class Viscosity extends Glyph {
private static final String TXT_VISCOSITY = "%s of viscosity";
private static ItemSprite.Glowing PURPLE = new ItemSprite.Glowing( 0x8844CC );
@Override
public int proc( Armor armor, Char attacker, Char defender, int damage ) {
if (damage == 0) {
return 0;
}
int level = Math.max( 0, armor.level );
if (Random.Int( level + 7 ) >= 6) {
DeferedDamage debuff = defender.buff( DeferedDamage.class );
if (debuff == null) {
debuff = new DeferedDamage();
debuff.attachTo( defender );
}
debuff.prolong( damage );
defender.sprite.showStatus( CharSprite.WARNING, "deferred %d", damage );
return 0;
} else {
return damage;
}
}
@Override
public String name( String weaponName) {
return String.format( TXT_VISCOSITY, weaponName );
}
@Override
public Glowing glowing() {
return PURPLE;
}
public static class DeferedDamage extends Buff {
protected int damage = 0;
private static final String DAMAGE = "damage";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( DAMAGE, damage );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
damage = bundle.getInt( DAMAGE );
}
@Override
public boolean attachTo( Char target ) {
if (super.attachTo( target )) {
postpone( TICK );
return true;
} else {
return false;
}
}
public void prolong( int damage ) {
this.damage += damage;
};
@Override
public int icon() {
return BuffIndicator.DEFERRED;
}
@Override
public String toString() {
return Utils.format( "Defered damage (%d)", damage );
}
@Override
public boolean act() {
if (target.isAlive()) {
target.damage( 1, this );
if (target == Dungeon.hero && !target.isAlive()) {
// Refactoring needed!
Glyph glyph = new Viscosity();
Dungeon.fail( Utils.format( ResultDescriptions.GLYPH, glyph.name(), Dungeon.depth ) );
GLog.n( "%s killed you...", glyph.name() );
Badges.validateDeathFromGlyph();
}
spend( TICK );
if (--damage <= 0) {
detach();
}
} else {
detach();
}
return true;
}
}
}
@@ -0,0 +1,186 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.bags;
import java.util.ArrayList;
import java.util.Iterator;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.watabou.utils.Bundlable;
import com.watabou.utils.Bundle;
public class Bag extends Item implements Iterable<Item> {
public static final String AC_OPEN = "OPEN";
{
image = 11;
defaultAction = AC_OPEN;
}
public Char owner;
public ArrayList<Item> items = new ArrayList<Item>();
public int size = 1;
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action.equals( AC_OPEN )) {
GameScene.show( new WndBag( this, null, WndBag.Mode.ALL, null ) );
} else {
super.execute( hero, action );
}
}
@Override
public boolean collect( Bag container ) {
if (super.collect( container )) {
owner = container.owner;
for (Item item : container.items.toArray( new Item[0] )) {
if (grab( item )) {
item.detachAll( container );
item.collect( this );
}
}
Badges.validateAllBagsBought( this );
return true;
} else {
return false;
}
}
@Override
public Item detach( Bag container ) {
owner = null;
return super.detach( container );
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
public void clear() {
items.clear();
}
private static final String ITEMS = "inventory";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( ITEMS, items );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
for (Bundlable item : bundle.getCollection( ITEMS )) {
((Item)item).collect( this );
};
}
public boolean contains( Item item ) {
for (Item i : items) {
if (i == item) {
return true;
} else if (i instanceof Bag && ((Bag)i).contains( item )) {
return true;
}
}
return false;
}
public boolean grab( Item item ) {
return false;
}
@Override
public Iterator<Item> iterator() {
return new ItemIterator();
}
private class ItemIterator implements Iterator<Item> {
private int index = 0;
private Iterator<Item> nested = null;
@Override
public boolean hasNext() {
if (nested != null) {
return nested.hasNext() || index < items.size();
} else {
return index < items.size();
}
}
@Override
public Item next() {
if (nested != null && nested.hasNext()) {
return nested.next();
} else {
nested = null;
Item item = items.get( index++ );
if (item instanceof Bag) {
nested = ((Bag)item).iterator();
}
return item;
}
}
@Override
public void remove() {
if (nested != null) {
nested.remove();
} else {
items.remove( index );
}
}
}
}
@@ -0,0 +1,49 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.bags;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class ScrollHolder extends Bag {
{
name = "scroll holder";
image = ItemSpriteSheet.HOLDER;
size = 12;
}
@Override
public boolean grab( Item item ) {
return item instanceof Scroll;
}
@Override
public int price() {
return 50;
}
@Override
public String info() {
return
"You can place any number of scrolls into this tubular container. " +
"It saves room in your backpack and protects scrolls from fire.";
}
}
@@ -0,0 +1,48 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.bags;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.plants.Plant;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class SeedPouch extends Bag {
{
name = "seed pouch";
image = ItemSpriteSheet.POUCH;
size = 8;
}
@Override
public boolean grab( Item item ) {
return item instanceof Plant.Seed;
}
@Override
public int price() {
return 50;
}
@Override
public String info() {
return
"This small velvet pouch allows you to store any number of seeds in it. Very convenient.";
}
}
@@ -0,0 +1,73 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.bags;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class WandHolster extends Bag {
{
name = "wand holster";
image = ItemSpriteSheet.HOLSTER;
size = 12;
}
@Override
public boolean grab( Item item ) {
return item instanceof Wand;
}
@Override
public boolean collect( Bag container ) {
if (super.collect( container )) {
if (owner != null) {
for (Item item : items) {
((Wand)item).charge( owner );
}
}
return true;
} else {
return false;
}
}
@Override
public Item detach( Bag container ) {
for (Item item : items) {
((Wand)item).stopCharging();
}
return super.detach( container );
}
@Override
public int price() {
return 50;
}
@Override
public String info() {
return
"This slim holder is made of leather of some exotic animal. " +
"It allows to compactly carry up to " + size + " wands.";
}
}
@@ -0,0 +1,46 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.food;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class ChargrilledMeat extends Food {
{
name = "chargrilled meat";
image = ItemSpriteSheet.STEAK;
energy = Hunger.STARVING - Hunger.HUNGRY;
}
@Override
public String info() {
return "It looks like a decent steak.";
}
@Override
public int price() {
return 5 * quantity;
}
public static Food cook( MysteryMeat ingredient ) {
ChargrilledMeat result = new ChargrilledMeat();
result.quantity = ingredient.quantity();
return result;
}
}
@@ -0,0 +1,120 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.food;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.SpellSprite;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class Food extends Item {
private static final float TIME_TO_EAT = 3f;
public static final String AC_EAT = "EAT";
public float energy = Hunger.HUNGRY;
public String message = "That food tasted delicious!";
{
stackable = true;
name = "ration of food";
image = ItemSpriteSheet.RATION;
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_EAT );
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action.equals( AC_EAT )) {
detach( hero.belongings.backpack );
((Hunger)hero.buff( Hunger.class )).satisfy( energy );
GLog.i( message );
switch (hero.heroClass) {
case WARRIOR:
if (hero.HP < hero.HT) {
hero.HP = Math.min( hero.HP + 5, hero.HT );
hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 );
}
break;
case MAGE:
hero.belongings.charge( false );
ScrollOfRecharging.charge( hero );
break;
case ROGUE:
case HUNTRESS:
break;
}
hero.sprite.operate( hero.pos );
hero.busy();
SpellSprite.show( hero, SpellSprite.FOOD );
Sample.INSTANCE.play( Assets.SND_EAT );
hero.spend( TIME_TO_EAT );
Statistics.foodEaten++;
Badges.validateFoodEaten();
} else {
super.execute( hero, action );
}
}
@Override
public String info() {
return
"Nothing fancy here: dried meat, " +
"some biscuits - things like that.";
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public int price() {
return 10 * quantity;
}
}
@@ -0,0 +1,92 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.food;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barkskin;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Random;
public class FrozenCarpaccio extends Food {
{
name = "frozen carpaccio";
image = ItemSpriteSheet.CARPACCIO;
energy = Hunger.STARVING - Hunger.HUNGRY;
}
@Override
public void execute( Hero hero, String action ) {
super.execute( hero, action );
if (action.equals( AC_EAT )) {
switch (Random.Int( 5 )) {
case 0:
GLog.i( "You see your hands turn invisible!" );
Buff.affect( hero, Invisibility.class, Invisibility.DURATION );
break;
case 1:
GLog.i( "You feel your skin hardens!" );
Buff.affect( hero, Barkskin.class ).level( hero.HT / 4 );
break;
case 2:
GLog.i( "Refreshing!" );
Buff.detach( hero, Poison.class );
Buff.detach( hero, Cripple.class );
Buff.detach( hero, Weakness.class );
Buff.detach( hero, Bleeding.class );
break;
case 3:
GLog.i( "You feel better!" );
if (hero.HP < hero.HT) {
hero.HP = Math.min( hero.HP + hero.HT / 4, hero.HT );
hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 );
}
break;
}
}
}
@Override
public String info() {
return
"It's a piece of frozen raw meat. The only way to eat it is " +
"by cutting thin slices of it. And this way it's suprisingly good.";
}
public int price() {
return 10 * quantity;
};
public static Food cook( MysteryMeat ingredient ) {
FrozenCarpaccio result = new FrozenCarpaccio();
result.quantity = ingredient.quantity();
return result;
}
}
@@ -0,0 +1,77 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.food;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Slow;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Random;
public class MysteryMeat extends Food {
{
name = "mystery meat";
image = ItemSpriteSheet.MEAT;
energy = Hunger.STARVING - Hunger.HUNGRY;
message = "That food tasted... strange.";
}
@Override
public void execute( Hero hero, String action ) {
super.execute( hero, action );
if (action.equals( AC_EAT )) {
switch (Random.Int( 5 )) {
case 0:
GLog.w( "Oh it's hot!" );
Buff.affect( hero, Burning.class ).reignite( hero );
break;
case 1:
GLog.w( "You can't feel your legs!" );
Buff.prolong( hero, Roots.class, Paralysis.duration( hero ) );
break;
case 2:
GLog.w( "You are not feeling well." );
Buff.affect( hero, Poison.class ).set( Poison.durationFactor( hero ) * hero.HT / 2 / Poison.DOT );
break;
case 3:
GLog.w( "You are stuffed." );
Buff.prolong( hero, Slow.class, Slow.duration( hero ) );
break;
}
}
}
@Override
public String info() {
return "Eat at your own risk!";
}
public int price() {
return 5 * quantity;
};
}
@@ -0,0 +1,41 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.food;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class OverpricedRation extends Food {
{
name = "overpriced food ration";
image = ItemSpriteSheet.OVERPRICED;
energy = Hunger.STARVING - Hunger.HUNGRY;
message = "That food tasted ok.";
}
@Override
public String info() {
return "It looks exactly like a standard ration of food but smaller.";
}
@Override
public int price() {
return 20 * quantity;
}
}
@@ -0,0 +1,40 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.food;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class Pasty extends Food {
{
name = "pasty";
image = ItemSpriteSheet.PASTY;
energy = Hunger.STARVING;
}
@Override
public String info() {
return "This is authentic Cornish pasty with traditional filling of beef and potato.";
}
@Override
public int price() {
return 20 * quantity;
}
}
@@ -0,0 +1,44 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.keys;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class GoldenKey extends Key {
{
name = "golden key";
image = ItemSpriteSheet.GOLDEN_KEY;
}
public GoldenKey() {
this( 0 );
}
public GoldenKey( int depth ) {
super();
this.depth = depth;
}
@Override
public String info() {
return
"The notches on this golden key are tiny and intricate. " +
"Maybe it can open some chest lock?";
}
}
@@ -0,0 +1,75 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.keys;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
public class IronKey extends Key {
private static final String TXT_FROM_DEPTH = "iron key from depth %d";
public static int curDepthQunatity = 0;
{
name = "iron key";
image = ItemSpriteSheet.IRON_KEY;
}
public IronKey() {
this( 0 );
}
public IronKey( int depth ) {
super();
this.depth = depth;
}
@Override
public boolean collect( Bag bag ) {
boolean result = super.collect( bag );
if (result && depth == Dungeon.depth && Dungeon.hero != null) {
Dungeon.hero.belongings.countIronKeys();
}
return result;
}
@Override
public Item detach( Bag bag ) {
Item result = super.detach( bag );
if (result != null && depth == Dungeon.depth) {
Dungeon.hero.belongings.countIronKeys();
}
return result;
}
@Override
public String toString() {
return Utils.format( TXT_FROM_DEPTH, depth );
}
@Override
public String info() {
return
"The notches on this ancient iron key are well worn; its leather lanyard " +
"is battered by age. What door might it open?";
}
}
@@ -0,0 +1,69 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.keys;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
import com.watabou.utils.Bundle;
public class Key extends Item {
public static final float TIME_TO_UNLOCK = 1f;
{
stackable = true;
}
public int depth;
@Override
public boolean isSimilar( Item item ) {
return item.getClass() == getClass() && ((Key)item).depth == depth;
}
@Override
public Item detach( Bag container ) {
Key key = (Key)super.detach( container );
key.depth = depth;
return key;
}
private static final String DEPTH = "depth";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( DEPTH, depth );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
depth = bundle.getInt( DEPTH );
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
}
@@ -0,0 +1,50 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.keys;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class SkeletonKey extends Key {
{
name = "skeleton key";
image = ItemSpriteSheet.SKELETON_KEY;
stackable = false;
}
public SkeletonKey() {
this( 0 );
}
public SkeletonKey( int depth ) {
super();
this.depth = depth;
}
@Override
public boolean isSimilar( Item item ) {
return false;
}
@Override
public String info() {
return
"This key looks serious: its head is shaped like a skull. Probably it can open some serious door.";
}
}
@@ -0,0 +1,287 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import java.util.ArrayList;
import java.util.HashSet;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.ItemStatusHandler;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
import com.watabou.utils.Bundle;
public class Potion extends Item {
public static final String AC_DRINK = "DRINK";
private static final String TXT_HARMFUL = "Harmful potion!";
private static final String TXT_BENEFICIAL = "Beneficial potion";
private static final String TXT_YES = "Yes, I know what I'm doing";
private static final String TXT_NO = "No, I changed my mind";
private static final String TXT_R_U_SURE_DRINK =
"Are you sure you want to drink it? In most cases you should throw such potions at your enemies.";
private static final String TXT_R_U_SURE_THROW =
"Are you sure you want to throw it? In most cases it makes sense to drink it.";
private static final float TIME_TO_DRINK = 1f;
private static final Class<?>[] potions = {
PotionOfHealing.class,
PotionOfExperience.class,
PotionOfToxicGas.class,
PotionOfLiquidFlame.class,
PotionOfStrength.class,
PotionOfParalyticGas.class,
PotionOfLevitation.class,
PotionOfMindVision.class,
PotionOfPurity.class,
PotionOfInvisibility.class,
PotionOfMight.class,
PotionOfFrost.class
};
private static final String[] colors = {
"turquoise", "crimson", "azure", "jade", "golden", "magenta",
"charcoal", "ivory", "amber", "bistre", "indigo", "silver"};
private static final Integer[] images = {
ItemSpriteSheet.POTION_TURQUOISE,
ItemSpriteSheet.POTION_CRIMSON,
ItemSpriteSheet.POTION_AZURE,
ItemSpriteSheet.POTION_JADE,
ItemSpriteSheet.POTION_GOLDEN,
ItemSpriteSheet.POTION_MAGENTA,
ItemSpriteSheet.POTION_CHARCOAL,
ItemSpriteSheet.POTION_IVORY,
ItemSpriteSheet.POTION_AMBER,
ItemSpriteSheet.POTION_BISTRE,
ItemSpriteSheet.POTION_INDIGO,
ItemSpriteSheet.POTION_SILVER};
private static ItemStatusHandler<Potion> handler;
private String color;
{
stackable = true;
defaultAction = AC_DRINK;
}
@SuppressWarnings("unchecked")
public static void initColors() {
handler = new ItemStatusHandler<Potion>( (Class<? extends Potion>[])potions, colors, images );
}
public static void save( Bundle bundle ) {
handler.save( bundle );
}
@SuppressWarnings("unchecked")
public static void restore( Bundle bundle ) {
handler = new ItemStatusHandler<Potion>( (Class<? extends Potion>[])potions, colors, images, bundle );
}
public Potion() {
super();
image = handler.image( this );
color = handler.label( this );
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_DRINK );
return actions;
}
@Override
public void execute( final Hero hero, String action ) {
if (action.equals( AC_DRINK )) {
if (isKnown() && (
this instanceof PotionOfLiquidFlame ||
this instanceof PotionOfToxicGas ||
this instanceof PotionOfParalyticGas)) {
GameScene.show(
new WndOptions( TXT_HARMFUL, TXT_R_U_SURE_DRINK, TXT_YES, TXT_NO ) {
@Override
protected void onSelect(int index) {
if (index == 0) {
drink( hero );
}
};
}
);
} else {
drink( hero );
}
} else {
super.execute( hero, action );
}
}
@Override
public void doThrow( final Hero hero ) {
if (isKnown() && (
this instanceof PotionOfExperience ||
this instanceof PotionOfHealing ||
this instanceof PotionOfLevitation ||
this instanceof PotionOfMindVision ||
this instanceof PotionOfStrength ||
this instanceof PotionOfInvisibility ||
this instanceof PotionOfMight)) {
GameScene.show(
new WndOptions( TXT_BENEFICIAL, TXT_R_U_SURE_THROW, TXT_YES, TXT_NO ) {
@Override
protected void onSelect(int index) {
if (index == 0) {
Potion.super.doThrow( hero );
}
};
}
);
} else {
super.doThrow( hero );
}
}
protected void drink( Hero hero ) {
detach( hero.belongings.backpack );
hero.spend( TIME_TO_DRINK );
hero.busy();
onThrow( hero.pos );
Sample.INSTANCE.play( Assets.SND_DRINK );
hero.sprite.operate( hero.pos );
}
@Override
protected void onThrow( int cell ) {
if (Dungeon.hero.pos == cell) {
apply( Dungeon.hero );
} else if (Dungeon.level.map[cell] == Terrain.WELL || Level.pit[cell]) {
super.onThrow( cell );
} else {
shatter( cell );
}
}
protected void apply( Hero hero ) {
shatter( hero.pos );
}
protected void shatter( int cell ) {
GLog.i( "The flask shatters and " + color() + " liquid splashes harmlessly" );
Sample.INSTANCE.play( Assets.SND_SHATTER );
splash( cell );
}
public boolean isKnown() {
return handler.isKnown( this );
}
public void setKnown() {
if (!isKnown()) {
handler.know( this );
}
Badges.validateAllPotionsIdentified();
}
@Override
public Item identify() {
setKnown();
return this;
}
protected String color() {
return color;
}
@Override
public String name() {
return isKnown() ? name : color + " potion";
}
@Override
public String info() {
return isKnown() ?
desc() :
"This flask contains a swirling " + color + " liquid. " +
"Who knows what it will do when drunk or thrown?";
}
@Override
public boolean isIdentified() {
return isKnown();
}
@Override
public boolean isUpgradable() {
return false;
}
public static HashSet<Class<? extends Potion>> getKnown() {
return handler.known();
}
public static HashSet<Class<? extends Potion>> getUnknown() {
return handler.unknown();
}
public static boolean allKnown() {
return handler.known().size() == potions.length;
}
protected void splash( int cell ) {
final int color = ItemSprite.pick( image, 8, 10 );
Splash.at( cell, color, 5 );
}
@Override
public int price() {
return 20 * quantity;
}
}
@@ -0,0 +1,45 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
public class PotionOfExperience extends Potion {
{
name = "Potion of Experience";
}
@Override
protected void apply( Hero hero ) {
setKnown();
hero.earnExp( hero.maxExp() - hero.exp );
}
@Override
public String desc() {
return
"The storied experiences of multitudes of battles reduced to liquid form, " +
"this draught will instantly raise your experience level.";
}
@Override
public int price() {
return isKnown() ? 80 * quantity : super.price();
}
}
@@ -0,0 +1,67 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Freezing;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
import com.watabou.utils.PathFinder;
public class PotionOfFrost extends Potion {
private static final int DISTANCE = 2;
{
name = "Potion of Frost";
}
@Override
protected void shatter( int cell ) {
PathFinder.buildDistanceMap( cell, BArray.not( Level.losBlocking, null ), DISTANCE );
Fire fire = (Fire)Dungeon.level.blobs.get( Fire.class );
for (int i=0; i < Level.LENGTH; i++) {
if (PathFinder.distance[i] < Integer.MAX_VALUE) {
Freezing.affect( i, fire );
}
}
splash( cell );
Sample.INSTANCE.play( Assets.SND_SHATTER );
setKnown();
}
@Override
public String desc() {
return
"Upon exposure to open air this chemical will evaporate into a freezing cloud, causing " +
"any creature that contacts it to be frozen in place unable to act and move.";
}
@Override
public int price() {
return isKnown() ? 50 * quantity : super.price();
}
}
@@ -0,0 +1,64 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class PotionOfHealing extends Potion {
{
name = "Potion of Healing";
}
@Override
protected void apply( Hero hero ) {
setKnown();
heal( Dungeon.hero );
GLog.p( "Your wounds heal completely." );
}
public static void heal( Hero hero ) {
hero.HP = hero.HT;
Buff.detach( hero, Poison.class );
Buff.detach( hero, Cripple.class );
Buff.detach( hero, Weakness.class );
Buff.detach( hero, Bleeding.class );
hero.sprite.emitter().start( Speck.factory( Speck.HEALING ), 0.4f, 4 );
}
@Override
public String desc() {
return
"An elixir that will instantly return you to full health and cure poison.";
}
@Override
public int price() {
return isKnown() ? 30 * quantity : super.price();
}
}
@@ -0,0 +1,65 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.tweeners.AlphaTweener;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class PotionOfInvisibility extends Potion {
private static final float ALPHA = 0.4f;
{
name = "Potion of Invisibility";
}
@Override
protected void apply( Hero hero ) {
setKnown();
Buff.affect( hero, Invisibility.class, Invisibility.DURATION );
GLog.i( "You see your hands turn invisible!" );
Sample.INSTANCE.play( Assets.SND_MELD );
}
@Override
public String desc() {
return
"Drinking this potion will render you temporarily invisible. While invisible, " +
"enemies will be unable to see you. Attacking an enemy, as well as using a wand or a scroll " +
"before enemy's eyes, will dispel the effect.";
}
@Override
public int price() {
return isKnown() ? 40 * quantity : super.price();
}
public static void melt( Char ch ) {
if (ch.sprite.parent != null) {
ch.sprite.parent.add( new AlphaTweener( ch.sprite, ALPHA, 0.4f ) );
} else {
ch.sprite.alpha( ALPHA );
}
}
}
@@ -0,0 +1,50 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Levitation;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class PotionOfLevitation extends Potion {
{
name = "Potion of Levitation";
}
@Override
protected void apply( Hero hero ) {
setKnown();
Buff.affect( hero, Levitation.class, Levitation.DURATION );
GLog.i( "You float into the air!" );
}
@Override
public String desc() {
return
"Drinking this curious liquid will cause you to hover in the air, " +
"able to drift effortlessly over traps. Flames and gases " +
"fill the air, however, and cannot be bypassed while airborne.";
}
@Override
public int price() {
return isKnown() ? 35 * quantity : super.price();
}
}
@@ -0,0 +1,55 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
public class PotionOfLiquidFlame extends Potion {
{
name = "Potion of Liquid Flame";
}
@Override
protected void shatter( int cell ) {
setKnown();
splash( cell );
Sample.INSTANCE.play( Assets.SND_SHATTER );
Fire fire = Blob.seed( cell, 2, Fire.class );
GameScene.add( fire );
}
@Override
public String desc() {
return
"This flask contains an unstable compound which will burst " +
"violently into flame upon exposure to open air.";
}
@Override
public int price() {
return isKnown() ? 40 * quantity : super.price();
}
}
@@ -0,0 +1,52 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class PotionOfMight extends PotionOfStrength {
{
name = "Potion of Might";
}
@Override
protected void apply( Hero hero ) {
setKnown();
hero.STR++;
hero.HT += 5;
hero.HP += 5;
hero.sprite.showStatus( CharSprite.POSITIVE, "+1 str, +5 ht" );
GLog.p( "Newfound strength surges through your body." );
}
@Override
public String desc() {
return
"This powerful liquid will course through your muscles, permanently " +
"increasing your strength by one point and health by five points.";
}
@Override
public int price() {
return isKnown() ? 200 * quantity : super.price();
}
}
@@ -0,0 +1,57 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class PotionOfMindVision extends Potion {
{
name = "Potion of Mind Vision";
}
@Override
protected void apply( Hero hero ) {
setKnown();
Buff.affect( hero, MindVision.class, MindVision.DURATION );
Dungeon.observe();
if (Dungeon.level.mobs.size() > 0) {
GLog.i( "You can somehow feel the presence of other creatures' minds!" );
} else {
GLog.i( "You can somehow tell that you are alone on this level at the moment." );
}
}
@Override
public String desc() {
return
"After drinking this, your mind will become attuned to the psychic signature " +
"of distant creatures, enabling you to sense biological presences through walls. " +
"Also this potion will permit you to see through nearby walls and doors.";
}
@Override
public int price() {
return isKnown() ? 35 * quantity : super.price();
}
}
@@ -0,0 +1,56 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ParalyticGas;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
public class PotionOfParalyticGas extends Potion {
{
name = "Potion of Paralytic Gas";
}
@Override
protected void shatter( int cell ) {
setKnown();
splash( cell );
Sample.INSTANCE.play( Assets.SND_SHATTER );
GameScene.add( Blob.seed( cell, 1000, ParalyticGas.class ) );
}
@Override
public String desc() {
return
"Upon exposure to open air, the liquid in this flask will vaporize " +
"into a numbing yellow haze. Anyone who inhales the cloud will be paralyzed " +
"instantly, unable to move for some time after the cloud dissipates. This " +
"item can be thrown at distant enemies to catch them within the effect of the gas.";
}
@Override
public int price() {
return isKnown() ? 40 * quantity : super.price();
}
}
@@ -0,0 +1,126 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ParalyticGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.GasesImmunity;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.PathFinder;
public class PotionOfPurity extends Potion {
private static final String TXT_FRESHNESS = "You feel uncommon freshness in the air.";
private static final String TXT_NO_SMELL = "You've stopped sensing any smells!";
private static final int DISTANCE = 2;
{
name = "Potion of Purification";
}
@Override
protected void shatter( int cell ) {
PathFinder.buildDistanceMap( cell, BArray.not( Level.losBlocking, null ), DISTANCE );
boolean procd = false;
Blob[] blobs = {
Dungeon.level.blobs.get( ToxicGas.class ),
Dungeon.level.blobs.get( ParalyticGas.class )
};
for (int j=0; j < blobs.length; j++) {
Blob blob = blobs[j];
if (blob == null) {
continue;
}
for (int i=0; i < Level.LENGTH; i++) {
if (PathFinder.distance[i] < Integer.MAX_VALUE) {
int value = blob.cur[i];
if (value > 0) {
blob.cur[i] = 0;
blob.volume -= value;
procd = true;
CellEmitter.get( i ).burst( Speck.factory( Speck.DISCOVER ), 1 );
}
}
}
}
boolean heroAffected = PathFinder.distance[Dungeon.hero.pos] < Integer.MAX_VALUE;
if (procd) {
splash( cell );
Sample.INSTANCE.play( Assets.SND_SHATTER );
setKnown();
if (heroAffected) {
GLog.p( TXT_FRESHNESS );
}
} else {
super.shatter( cell );
if (heroAffected) {
GLog.i( TXT_FRESHNESS );
setKnown();
}
}
}
@Override
protected void apply( Hero hero ) {
GLog.w( TXT_NO_SMELL );
Buff.prolong( hero, GasesImmunity.class, GasesImmunity.DURATION );
setKnown();
}
@Override
public String desc() {
return
"This reagent will quickly neutralize all harmful gases in the area of effect. " +
"Drinking it will give you a temporary immunity to such gases.";
}
@Override
public int price() {
return isKnown() ? 50 * quantity : super.price();
}
}
@@ -0,0 +1,53 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class PotionOfStrength extends Potion {
{
name = "Potion of Strength";
}
@Override
protected void apply( Hero hero ) {
setKnown();
hero.STR++;
hero.sprite.showStatus( CharSprite.POSITIVE, "+1 str" );
GLog.p( "Newfound strength surges through your body." );
Badges.validateStrengthAttained();
}
@Override
public String desc() {
return
"This powerful liquid will course through your muscles, " +
"permanently increasing your strength by one point.";
}
@Override
public int price() {
return isKnown() ? 100 * quantity : super.price();
}
}
@@ -0,0 +1,59 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.potions;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
public class PotionOfToxicGas extends Potion {
{
name = "Potion of Toxic Gas";
}
@Override
protected void shatter( int cell ) {
setKnown();
splash( cell );
Sample.INSTANCE.play( Assets.SND_SHATTER );
ToxicGas gas = Blob.seed( cell, 1000, ToxicGas.class );
Actor.add( gas );
GameScene.add( gas );
}
@Override
public String desc() {
return
"Uncorking or shattering this pressurized glass will cause " +
"its contents to explode into a deadly cloud of toxic green gas. " +
"You might choose to fling this potion at distant enemies " +
"instead of uncorking it by hand.";
}
@Override
public int price() {
return isKnown() ? 40 * quantity : super.price();
}
}
@@ -0,0 +1,51 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.quest;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class CorpseDust extends Item {
{
name = "corpse dust";
image = ItemSpriteSheet.DUST;
cursed = true;
cursedKnown = true;
unique = true;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public String info() {
return
"The ball of corpse dust doesn't differ outwardly from a regular dust ball. However, " +
"you know somehow that it's better to get rid of it as soon as possible.";
}
}
@@ -0,0 +1,54 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.quest;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class DarkGold extends Item {
{
name = "dark gold ore";
image = ItemSpriteSheet.ORE;
stackable = true;
unique = true;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public String info() {
return
"This metal is called dark not because of its color (it doesn't differ from the normal gold), " +
"but because it melts under the daylight, making it useless on the surface.";
}
@Override
public int price() {
return quantity;
}
}
@@ -0,0 +1,47 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.quest;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class DriedRose extends Item {
{
name = "dried rose";
image = ItemSpriteSheet.ROSE;
unique = true;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public String info() {
return
"The rose has dried long ago, but it has kept all its petals somehow.";
}
}
@@ -0,0 +1,54 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.quest;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class DwarfToken extends Item {
{
name = "dwarf token";
image = ItemSpriteSheet.TOKEN;
stackable = true;
unique = true;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public String info() {
return
"Many dwarves and some of their larger creations carry these small pieces of metal of unknown purpose. " +
"Maybe they are jewelry or maybe some kind of ID. Dwarves are strange folk.";
}
@Override
public int price() {
return quantity * 100;
}
}
@@ -0,0 +1,177 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.quest;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bat;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite.Glowing;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
public class Pickaxe extends Weapon {
public static final String AC_MINE = "MINE";
public static final float TIME_TO_MINE = 2;
private static final String TXT_NO_VEIN = "There is no dark gold vein near you to mine";
private static final Glowing BLOODY = new Glowing( 0x550000 );
{
name = "pickaxe";
image = ItemSpriteSheet.PICKAXE;
unique = true;
defaultAction = AC_MINE;
STR = 14;
MIN = 3;
MAX = 12;
}
public boolean bloodStained = false;
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_MINE );
return actions;
}
@Override
public void execute( final Hero hero, String action ) {
if (action == AC_MINE) {
if (Dungeon.depth < 11 || Dungeon.depth > 15) {
GLog.w( TXT_NO_VEIN );
return;
}
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
final int pos = hero.pos + Level.NEIGHBOURS8[i];
if (Dungeon.level.map[pos] == Terrain.WALL_DECO) {
hero.spend( TIME_TO_MINE );
hero.busy();
hero.sprite.attack( pos, new Callback() {
@Override
public void call() {
CellEmitter.center( pos ).burst( Speck.factory( Speck.STAR ), 7 );
Sample.INSTANCE.play( Assets.SND_EVOKE );
Level.set( pos, Terrain.WALL );
GameScene.updateMap( pos );
DarkGold gold = new DarkGold();
if (gold.doPickUp( Dungeon.hero )) {
GLog.i( Hero.TXT_YOU_NOW_HAVE, gold.name() );
} else {
Dungeon.level.drop( gold, hero.pos ).sprite.drop();
}
Hunger hunger = hero.buff( Hunger.class );
if (hunger != null && !hunger.isStarving()) {
hunger.satisfy( -Hunger.STARVING / 10 );
BuffIndicator.refreshHero();
}
hero.onOperateComplete();
}
} );
return;
}
}
GLog.w( TXT_NO_VEIN );
} else {
super.execute( hero, action );
}
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public void proc( Char attacker, Char defender, int damage ) {
if (!bloodStained && defender instanceof Bat && (defender.HP <= damage)) {
bloodStained = true;
updateQuickslot();
}
}
private static final String BLOODSTAINED = "bloodStained";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( BLOODSTAINED, bloodStained );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
bloodStained = bundle.getBoolean( BLOODSTAINED );
}
@Override
public Glowing glowing() {
return bloodStained ? BLOODY : null;
}
@Override
public String info() {
return
"This is a large and sturdy tool for breaking rocks. Probably it can be used as a weapon.";
}
}
@@ -0,0 +1,52 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.quest;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class RatSkull extends Item {
{
name = "giant rat skull";
image = ItemSpriteSheet.SKULL;
unique = true;
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return true;
}
@Override
public String info() {
return
"It could be a nice hunting trophy, but it smells too bad to place it on a wall.";
}
@Override
public int price() {
return 100;
}
}
@@ -0,0 +1,324 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
import java.util.ArrayList;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.ItemStatusHandler;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
public class Ring extends EquipableItem {
private static final float TIME_TO_EQUIP = 1f;
private static final String TXT_IDENTIFY =
"you are now familiar enough with your %s to identify it. It is %s.";
protected Buff buff;
private static final Class<?>[] rings = {
RingOfMending.class,
RingOfDetection.class,
RingOfShadows.class,
RingOfPower.class,
RingOfHerbalism.class,
RingOfAccuracy.class,
RingOfEvasion.class,
RingOfSatiety.class,
RingOfHaste.class,
RingOfHaggler.class,
RingOfElements.class,
RingOfThorns.class
};
private static final String[] gems =
{"diamond", "opal", "garnet", "ruby", "amethyst", "topaz", "onyx", "tourmaline", "emerald", "sapphire", "quartz", "agate"};
private static final Integer[] images = {
ItemSpriteSheet.RING_DIAMOND,
ItemSpriteSheet.RING_OPAL,
ItemSpriteSheet.RING_GARNET,
ItemSpriteSheet.RING_RUBY,
ItemSpriteSheet.RING_AMETHYST,
ItemSpriteSheet.RING_TOPAZ,
ItemSpriteSheet.RING_ONYX,
ItemSpriteSheet.RING_TOURMALINE,
ItemSpriteSheet.RING_EMERALD,
ItemSpriteSheet.RING_SAPPHIRE,
ItemSpriteSheet.RING_QUARTZ,
ItemSpriteSheet.RING_AGATE};
private static ItemStatusHandler<Ring> handler;
private String gem;
private int ticksToKnow = 200;
@SuppressWarnings("unchecked")
public static void initGems() {
handler = new ItemStatusHandler<Ring>( (Class<? extends Ring>[])rings, gems, images );
}
public static void save( Bundle bundle ) {
handler.save( bundle );
}
@SuppressWarnings("unchecked")
public static void restore( Bundle bundle ) {
handler = new ItemStatusHandler<Ring>( (Class<? extends Ring>[])rings, gems, images, bundle );
}
public Ring() {
super();
syncGem();
}
public void syncGem() {
image = handler.image( this );
gem = handler.label( this );
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( isEquipped( hero ) ? AC_UNEQUIP : AC_EQUIP );
return actions;
}
@Override
public boolean doEquip( Hero hero ) {
if (hero.belongings.ring1 != null && hero.belongings.ring2 != null) {
GLog.w( "you can only wear 2 rings at a time" );
return false;
} else {
if (hero.belongings.ring1 == null) {
hero.belongings.ring1 = this;
} else {
hero.belongings.ring2 = this;
}
detach( hero.belongings.backpack );
activate( hero );
cursedKnown = true;
if (cursed) {
equipCursed( hero );
GLog.n( "your " + this + " tightens around your finger painfully" );
}
hero.spendAndNext( TIME_TO_EQUIP );
return true;
}
}
public void activate( Char ch ) {
buff = buff();
buff.attachTo( ch );
}
@Override
public boolean doUnequip( Hero hero, boolean collect ) {
if (cursed) {
GLog.w( "You can't remove cursed " + name() + "!" );
return false;
}
if (hero.belongings.ring1 == this) {
hero.belongings.ring1 = null;
} else {
hero.belongings.ring2 = null;
}
hero.remove( buff );
buff = null;
hero.spendAndNext( TIME_TO_EQUIP );
if (collect && !collect( hero.belongings.backpack )) {
Dungeon.level.drop( this, hero.pos );
}
return true;
}
@Override
public boolean isEquipped( Hero hero ) {
return hero.belongings.ring1 == this || hero.belongings.ring2 == this;
}
@Override
public Item upgrade() {
super.upgrade();
if (buff != null) {
Char owner = buff.target;
buff.detach();
if ((buff = buff()) != null) {
buff.attachTo( owner );
}
}
return this;
}
public boolean isKnown() {
return handler.isKnown( this );
}
protected void setKnown() {
if (!isKnown()) {
handler.know( this );
}
Badges.validateAllRingsIdentified();
}
@Override
public String name() {
return isKnown() ? name : gem + " ring";
}
@Override
public String desc() {
return
"This metal band is adorned with a large " + gem + " gem " +
"that glitters in the darkness. Who knows what effect it has when worn?";
}
@Override
public String info() {
if (isEquipped( Dungeon.hero )) {
return desc() + "\n\n" + "The " + name() + " is on your finger" +
(cursed ? ", and because it is cursed, you are powerless to remove it." : "." );
} else if (cursed && cursedKnown) {
return desc() + "\n\nYou can feel a malevolent magic lurking within the " + name() + ".";
} else {
return desc();
}
}
@Override
public boolean isIdentified() {
return super.isIdentified() && isKnown();
}
@Override
public Item identify() {
setKnown();
return super.identify();
}
@Override
public Item random() {
level = Random.Int( 1, 3 );
if (Random.Float() < 0.3f) {
level = -level;
cursed = true;
}
return this;
}
public static boolean allKnown() {
return handler.known().size() == rings.length - 2;
}
@Override
public int price() {
int price = 80;
if (cursed && cursedKnown) {
price /= 2;
}
if (levelKnown) {
if (level > 0) {
price *= (level + 1);
} else if (level < 0) {
price /= (1 - level);
}
}
if (price < 1) {
price = 1;
}
return price;
}
protected RingBuff buff() {
return null;
}
public class RingBuff extends Buff {
private static final String TXT_KNOWN = "This is a %s";
public int level;
public RingBuff() {
level = Ring.this.level;
}
@Override
public boolean attachTo( Char target ) {
if (target instanceof Hero && ((Hero)target).heroClass == HeroClass.ROGUE && !isKnown()) {
setKnown();
GLog.i( TXT_KNOWN, name() );
Badges.validateItemLevelAquired( Ring.this );
}
return super.attachTo(target);
}
@Override
public boolean act() {
if (!isIdentified() && --ticksToKnow <= 0) {
String gemName = name();
identify();
GLog.w( TXT_IDENTIFY, gemName, Ring.this.toString() );
Badges.validateItemLevelAquired( Ring.this );
}
spend( TICK );
return true;
}
}
}
@@ -0,0 +1,40 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
public class RingOfAccuracy extends Ring {
{
name = "Ring of Accuracy";
}
@Override
protected RingBuff buff( ) {
return new Accuracy();
}
@Override
public String desc() {
return isKnown() ?
"This ring increases your chance to hit the enemy." :
super.desc();
}
public class Accuracy extends RingBuff {
}
}
@@ -0,0 +1,55 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
public class RingOfDetection extends Ring {
{
name = "Ring of Detection";
}
@Override
public boolean doEquip( Hero hero ) {
if (super.doEquip( hero )) {
Dungeon.hero.search( false );
return true;
} else {
return false;
}
}
@Override
protected RingBuff buff( ) {
return new Detection();
}
@Override
public String desc() {
return isKnown() ?
"Wearing this ring will allow the wearer to notice hidden secrets - " +
"traps and secret doors - without taking time to search. Degraded rings of detection " +
"will dull your senses, making it harder to notice secrets even when actively searching for them." :
super.desc();
}
public class Detection extends RingBuff {
}
}
@@ -0,0 +1,77 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
import java.util.HashSet;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Eye;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Warlock;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.LightningTrap;
import com.watabou.utils.Random;
public class RingOfElements extends Ring {
{
name = "Ring of Elements";
}
@Override
protected RingBuff buff( ) {
return new Resistance();
}
@Override
public String desc() {
return isKnown() ?
"This ring provides resistance to different elements, such as fire, " +
"electricity, gases etc. Also it decreases duration of negative effects." :
super.desc();
}
private static final HashSet<Class<?>> EMPTY = new HashSet<Class<?>>();
private static final HashSet<Class<?>> FULL;
static {
FULL = new HashSet<Class<?>>();
FULL.add( Burning.class );
FULL.add( ToxicGas.class );
FULL.add( Poison.class );
FULL.add( LightningTrap.Electricity.class );
FULL.add( Warlock.class );
FULL.add( Eye.class );
FULL.add( Yog.BurningFist.class );
}
public class Resistance extends RingBuff {
public HashSet<Class<?>> resistances() {
if (Random.Int( level + 3 ) >= 3) {
return FULL;
} else {
return EMPTY;
}
}
public float durationFactor() {
return level < 0 ? 1 : (2 + 0.5f * level) / (2 + level);
}
}
}
@@ -0,0 +1,40 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
public class RingOfEvasion extends Ring {
{
name = "Ring of Evasion";
}
@Override
protected RingBuff buff( ) {
return new Evasion();
}
@Override
public String desc() {
return isKnown() ?
"This ring increases your chance to dodge enemy attack." :
super.desc();
}
public class Evasion extends RingBuff {
}
}
@@ -0,0 +1,68 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
public class RingOfHaggler extends Ring {
{
name = "Ring of Haggler";
}
@Override
protected RingBuff buff( ) {
return new Haggling();
}
@Override
public Item random() {
level = +1;
return this;
}
@Override
public boolean doPickUp( Hero hero ) {
identify();
Badges.validateRingOfHaggler();
Badges.validateItemLevelAquired( this );
return super.doPickUp(hero);
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public String desc() {
return isKnown() ?
"In fact this ring doesn't provide any magic effect, but it demonstrates " +
"to shopkeepers and vendors, that the owner of the ring is a member of " +
"The Thieves' Guild. Usually they are glad to give a discount in exchange " +
"for temporary immunity guarantee. Upgrading this ring won't give any additional " +
"bonuses." :
super.desc();
}
public class Haggling extends RingBuff {
}
}
@@ -0,0 +1,40 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
public class RingOfHaste extends Ring {
{
name = "Ring of Haste";
}
@Override
protected RingBuff buff( ) {
return new Haste();
}
@Override
public String desc() {
return isKnown() ?
"This ring accelerates the wearer's flow of time, allowing one to perform all actions a little faster." :
super.desc();
}
public class Haste extends RingBuff {
}
}
@@ -0,0 +1,40 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
public class RingOfHerbalism extends Ring {
{
name = "Ring of Herbalism";
}
@Override
protected RingBuff buff( ) {
return new Herbalism();
}
@Override
public String desc() {
return isKnown() ?
"This ring increases your chance to gather dew and seeds from trampled grass." :
super.desc();
}
public class Herbalism extends RingBuff {
}
}
@@ -0,0 +1,42 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
public class RingOfMending extends Ring {
{
name = "Ring of Mending";
}
@Override
protected RingBuff buff( ) {
return new Rejuvenation();
}
@Override
public String desc() {
return isKnown() ?
"This ring increases the body's regenerative properties, allowing " +
"one to recover lost health at an accelerated rate. Degraded rings will " +
"decrease or even halt one's natural regeneration." :
super.desc();
}
public class Rejuvenation extends RingBuff {
}
}
@@ -0,0 +1,41 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
public class RingOfPower extends Ring {
{
name = "Ring of Power";
}
@Override
protected RingBuff buff( ) {
return new Power();
}
@Override
public String desc() {
return isKnown() ?
"Your wands will become more powerful in the energy field " +
"that radiates from this ring. Degraded rings of power will instead weaken your wands." :
super.desc();
}
public class Power extends RingBuff {
}
}
@@ -0,0 +1,40 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
public class RingOfSatiety extends Ring {
{
name = "Ring of Satiety";
}
@Override
protected RingBuff buff( ) {
return new Satiety();
}
@Override
public String desc() {
return isKnown() ?
"Wearing this ring you can go without food longer. Degraded rings of satiety will cause the opposite effect." :
super.desc();
}
public class Satiety extends RingBuff {
}
}
@@ -0,0 +1,41 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
public class RingOfShadows extends Ring {
{
name = "Ring of Shadows";
}
@Override
protected RingBuff buff( ) {
return new Shadows();
}
@Override
public String desc() {
return isKnown() ?
"Enemies will be less likely to notice you if you wear this ring. Degraded rings " +
"of shadows will alert enemies who might otherwise not have noticed your presence." :
super.desc();
}
public class Shadows extends RingBuff {
}
}
@@ -0,0 +1,66 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.rings;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
public class RingOfThorns extends Ring {
{
name = "Ring of Thorns";
}
@Override
protected RingBuff buff( ) {
return new Thorns();
}
@Override
public Item random() {
level = +1;
return this;
}
@Override
public boolean doPickUp( Hero hero ) {
identify();
Badges.validateRingOfThorns();
Badges.validateItemLevelAquired( this );
return super.doPickUp(hero);
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public String desc() {
return isKnown() ?
"Though this ring doesn't provide real thorns, an enemy that attacks you " +
"will itself be wounded by a fraction of the damage that it inflicts. " +
"Upgrading this ring won't give any additional bonuses." :
super.desc();
}
public class Thorns extends RingBuff {
}
}
@@ -0,0 +1,95 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
public abstract class InventoryScroll extends Scroll {
protected String inventoryTitle = "Select an item";
protected WndBag.Mode mode = WndBag.Mode.ALL;
private static final String TXT_WARNING =
"Do you really want to cancel this scroll usage? " +
"It will be consumed anyway.";
private static final String TXT_YES = "Yes, I'm positive";
private static final String TXT_NO = "No, I changed my mind";
@Override
protected void doRead() {
if (!isKnown()) {
setKnown();
identifiedByUse = true;
} else {
identifiedByUse = false;
}
GameScene.selectItem( itemSelector, mode, inventoryTitle );
}
private void confirmCancelation() {
GameScene.show( new WndOptions( name(), TXT_WARNING, TXT_YES, TXT_NO ) {
@Override
protected void onSelect( int index ) {
switch (index) {
case 0:
curUser.spendAndNext( TIME_TO_READ );
identifiedByUse = false;
break;
case 1:
GameScene.selectItem( itemSelector, mode, inventoryTitle );
break;
}
}
public void onBackPressed() {};
} );
}
protected abstract void onItemSelected( Item item );
protected static boolean identifiedByUse = false;
protected static WndBag.Listener itemSelector = new WndBag.Listener() {
@Override
public void onSelect( Item item ) {
if (item != null) {
((InventoryScroll)curItem).onItemSelected( item );
curUser.spendAndNext( TIME_TO_READ );
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
} else if (identifiedByUse) {
((InventoryScroll)curItem).confirmCancelation();
} else {
curItem.collect( curUser.belongings.backpack );
}
}
};
}
@@ -0,0 +1,184 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import java.util.ArrayList;
import java.util.HashSet;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.ItemStatusHandler;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
public abstract class Scroll extends Item {
private static final String TXT_BLINDED = "You can't read a scroll while blinded";
public static final String AC_READ = "READ";
protected static final float TIME_TO_READ = 1f;
private static final Class<?>[] scrolls = {
ScrollOfIdentify.class,
ScrollOfMagicMapping.class,
ScrollOfRecharging.class,
ScrollOfRemoveCurse.class,
ScrollOfTeleportation.class,
ScrollOfUpgrade.class,
ScrollOfRage.class,
ScrollOfTerror.class,
ScrollOfLullaby.class,
ScrollOfWeaponUpgrade.class,
ScrollOfPsionicBlast.class,
ScrollOfMirrorImage.class
};
private static final String[] runes =
{"KAUNAN", "SOWILO", "LAGUZ", "YNGVI", "GYFU", "RAIDO", "ISAZ", "MANNAZ", "NAUDIZ", "BERKANAN", "ODAL", "TIWAZ"};
private static final Integer[] images = {
ItemSpriteSheet.SCROLL_KAUNAN,
ItemSpriteSheet.SCROLL_SOWILO,
ItemSpriteSheet.SCROLL_LAGUZ,
ItemSpriteSheet.SCROLL_YNGVI,
ItemSpriteSheet.SCROLL_GYFU,
ItemSpriteSheet.SCROLL_RAIDO,
ItemSpriteSheet.SCROLL_ISAZ,
ItemSpriteSheet.SCROLL_MANNAZ,
ItemSpriteSheet.SCROLL_NAUDIZ,
ItemSpriteSheet.SCROLL_BERKANAN,
ItemSpriteSheet.SCROLL_ODAL,
ItemSpriteSheet.SCROLL_TIWAZ};
private static ItemStatusHandler<Scroll> handler;
private String rune;
{
stackable = true;
defaultAction = AC_READ;
}
@SuppressWarnings("unchecked")
public static void initLabels() {
handler = new ItemStatusHandler<Scroll>( (Class<? extends Scroll>[])scrolls, runes, images );
}
public static void save( Bundle bundle ) {
handler.save( bundle );
}
@SuppressWarnings("unchecked")
public static void restore( Bundle bundle ) {
handler = new ItemStatusHandler<Scroll>( (Class<? extends Scroll>[])scrolls, runes, images, bundle );
}
public Scroll() {
super();
image = handler.image( this );
rune = handler.label( this );
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
actions.add( AC_READ );
return actions;
}
@Override
public void execute( Hero hero, String action ) {
if (action.equals( AC_READ )) {
if (hero.buff( Blindness.class ) != null) {
GLog.w( TXT_BLINDED );
} else {
curUser = hero;
curItem = detach( hero.belongings.backpack );
doRead();
}
} else {
super.execute( hero, action );
}
}
abstract protected void doRead();
public boolean isKnown() {
return handler.isKnown( this );
}
public void setKnown() {
if (!isKnown()) {
handler.know( this );
}
Badges.validateAllScrollsIdentified();
}
@Override
public Item identify() {
setKnown();
return super.identify();
}
@Override
public String name() {
return isKnown() ? name : "scroll \"" + rune + "\"";
}
@Override
public String info() {
return isKnown() ?
desc() :
"This parchment is covered with indecipherable writing, and bears a title " +
"of rune " + rune + ". Who knows what it will do when read aloud?";
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isIdentified() {
return isKnown();
}
public static HashSet<Class<? extends Scroll>> getKnown() {
return handler.known();
}
public static HashSet<Class<? extends Scroll>> getUnknown() {
return handler.unknown();
}
public static boolean allKnown() {
return handler.known().size() == scrolls.length;
}
@Override
public int price() {
return 15 * quantity;
}
}
@@ -0,0 +1,55 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.effects.Identification;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
public class ScrollOfIdentify extends InventoryScroll {
{
name = "Scroll of Identify";
inventoryTitle = "Select an item to identify";
mode = WndBag.Mode.UNIDENTIFED;
}
@Override
protected void onItemSelected( Item item ) {
curUser.sprite.parent.add( new Identification( curUser.sprite.center().offset( 0, -16 ) ) );
item.identify();
GLog.i( "It is " + item );
Badges.validateItemLevelAquired( item );
}
@Override
public String desc() {
return
"Permanently reveals all of the secrets of a single item.";
}
@Override
public int price() {
return isKnown() ? 30 * quantity : super.price();
}
}
@@ -0,0 +1,82 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class ScrollOfLullaby extends Scroll {
{
name = "Scroll of Lullaby";
}
@Override
protected void doRead() {
curUser.sprite.centerEmitter().start( Speck.factory( Speck.NOTE ), 0.3f, 5 );
Sample.INSTANCE.play( Assets.SND_LULLABY );
Invisibility.dispel();
int count = 0;
Mob affected = null;
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (Level.fieldOfView[mob.pos]) {
Buff.affect( mob, Sleep.class );
if (mob.buff( Sleep.class ) != null) {
affected = mob;
count++;
}
}
}
switch (count) {
case 0:
GLog.i( "The scroll utters a soothing melody." );
break;
case 1:
GLog.i( "The scroll utters a soothing melody and the " + affected.name + " falls asleep!" );
break;
default:
GLog.i( "The scroll utters a soothing melody and the monsters fall asleep!" );
}
setKnown();
curUser.spendAndNext( TIME_TO_READ );
}
@Override
public String desc() {
return
"A soothing melody will put all creatures in your field of view into a deep sleep, " +
"giving you a chance to flee or make a surprise attack on them.";
}
@Override
public int price() {
return isKnown() ? 50 * quantity : super.price();
}
}
@@ -0,0 +1,103 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.SpellSprite;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class ScrollOfMagicMapping extends Scroll {
private static final String TXT_LAYOUT = "You are now aware of the level layout.";
{
name = "Scroll of Magic Mapping";
}
@Override
protected void doRead() {
int length = Level.LENGTH;
int[] map = Dungeon.level.map;
boolean[] mapped = Dungeon.level.mapped;
boolean[] discoverable = Level.discoverable;
boolean noticed = false;
for (int i=0; i < length; i++) {
int terr = map[i];
if (discoverable[i]) {
mapped[i] = true;
if ((Terrain.flags[terr] & Terrain.SECRET) != 0) {
Level.set( i, Terrain.discover( terr ) );
GameScene.updateMap( i );
if (Dungeon.visible[i]) {
GameScene.discoverTile( i, terr );
discover( i );
noticed = true;
}
}
}
}
Dungeon.observe();
GLog.i( TXT_LAYOUT );
if (noticed) {
Sample.INSTANCE.play( Assets.SND_SECRET );
}
SpellSprite.show( curUser, SpellSprite.MAP );
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
setKnown();
curUser.spendAndNext( TIME_TO_READ );
}
@Override
public String desc() {
return
"When this scroll is read, an image of crystal clarity will be etched into your memory, " +
"alerting you to the precise layout of the level and revealing all hidden secrets. " +
"The locations of items and creatures will remain unknown.";
}
@Override
public int price() {
return isKnown() ? 25 * quantity : super.price();
}
public static void discover( int cell ) {
CellEmitter.get( cell ).start( Speck.factory( Speck.DISCOVER ), 0.1f, 4 );
}
}
@@ -0,0 +1,80 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.MirrorImage;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.watabou.utils.Random;
public class ScrollOfMirrorImage extends Scroll {
private static final int NIMAGES = 3;
{
name = "Scroll of Mirror Image";
}
@Override
protected void doRead() {
ArrayList<Integer> respawnPoints = new ArrayList<Integer>();
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
int p = curUser.pos + Level.NEIGHBOURS8[i];
if (Actor.findChar( p ) == null && (Level.passable[p] || Level.avoid[p])) {
respawnPoints.add( p );
}
}
int nImages = NIMAGES;
while (nImages > 0 && respawnPoints.size() > 0) {
int index = Random.index( respawnPoints );
MirrorImage mob = new MirrorImage();
mob.duplicate( curUser );
GameScene.add( mob );
WandOfBlink.appear( mob, respawnPoints.get( index ) );
respawnPoints.remove( index );
nImages--;
}
if (nImages < NIMAGES) {
setKnown();
}
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
curUser.spendAndNext( TIME_TO_READ );
}
@Override
public String desc() {
return
"The incantation on this scroll will create illusionary twins of the reader, which will chase his enemies.";
}
}
@@ -0,0 +1,72 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.watabou.utils.Random;
public class ScrollOfPsionicBlast extends Scroll {
{
name = "Scroll of Psionic Blast";
}
@Override
protected void doRead() {
GameScene.flash( 0xFFFFFF );
Sample.INSTANCE.play( Assets.SND_BLAST );
Invisibility.dispel();
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (Level.fieldOfView[mob.pos]) {
Buff.prolong( mob, Blindness.class, Random.Int( 3, 6 ) );
mob.damage( Random.IntRange( 1, mob.HT * 2 / 3 ), this );
}
}
Buff.prolong( curUser, Blindness.class, Random.Int( 3, 6 ) );
Dungeon.observe();
setKnown();
curUser.spendAndNext( TIME_TO_READ );
}
@Override
public String desc() {
return
"This scroll contains destructive energy, that can be psionically channeled to inflict a " +
"massive damage to all creatures within a field of view. An accompanying flash of light will " +
"temporarily blind everybody in the area of effect including the reader of the scroll.";
}
@Override
public int price() {
return isKnown() ? 80 * quantity : super.price();
}
}
@@ -0,0 +1,62 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class ScrollOfRage extends Scroll {
{
name = "Scroll of Rage";
}
@Override
protected void doRead() {
for (Mob mob : Dungeon.level.mobs) {
mob.beckon( curUser.pos );
if (Dungeon.level.fieldOfView[mob.pos]) {
Buff.prolong(mob, Amok.class, 5f);
}
}
GLog.w( "The scroll emits an enraging roar that echoes throughout the dungeon!" );
setKnown();
curUser.sprite.centerEmitter().start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
Sample.INSTANCE.play( Assets.SND_CHALLENGE );
Invisibility.dispel();
curUser.spendAndNext( TIME_TO_READ );
}
@Override
public String desc() {
return
"When read aloud, this scroll will unleash a great roar " +
"that draws all enemies to the reader, and enrages nearby ones.";
}
}
@@ -0,0 +1,69 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.SpellSprite;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.EnergyParticle;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class ScrollOfRecharging extends Scroll {
{
name = "Scroll of Recharging";
}
@Override
protected void doRead() {
int count = curUser.belongings.charge( true );
charge( curUser );
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
if (count > 0) {
GLog.i( "a surge of energy courses through your pack, recharging your wand" + (count > 1 ? "s" : "") );
SpellSprite.show( curUser, SpellSprite.CHARGE );
} else {
GLog.i( "a surge of energy courses through your pack, but nothing happens" );
}
setKnown();
curUser.spendAndNext( TIME_TO_READ );
}
@Override
public String desc() {
return
"The raw magical power bound up in this parchment will, when released, " +
"recharge all of the reader's wands to full power.";
}
public static void charge( Hero hero ) {
hero.sprite.centerEmitter().burst( EnergyParticle.FACTORY, 15 );
}
@Override
public int price() {
return isKnown() ? 40 * quantity : super.price();
}
}
@@ -0,0 +1,98 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class ScrollOfRemoveCurse extends Scroll {
private static final String TXT_PROCCED =
"Your pack glows with a cleansing light, and a malevolent energy disperses.";
private static final String TXT_NOT_PROCCED =
"Your pack glows with a cleansing light, but nothing happens.";
{
name = "Scroll of Remove Curse";
}
@Override
protected void doRead() {
new Flare( 6, 32 ).show( curUser.sprite, 2f ) ;
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
boolean procced = uncurse( curUser, curUser.belongings.backpack.items.toArray( new Item[0] ) );
procced = uncurse( curUser,
curUser.belongings.weapon,
curUser.belongings.armor,
curUser.belongings.ring1,
curUser.belongings.ring2 ) || procced;
Weakness.detach( curUser, Weakness.class );
if (procced) {
GLog.p( TXT_PROCCED );
} else {
GLog.i( TXT_NOT_PROCCED );
}
setKnown();
curUser.spendAndNext( TIME_TO_READ );
}
@Override
public String desc() {
return
"The incantation on this scroll will instantly strip from " +
"the reader's weapon, armor, rings and carried items any evil " +
"enchantments that might prevent the wearer from removing them.";
}
public static boolean uncurse( Hero hero, Item... items ) {
boolean procced = false;
for (int i=0; i < items.length; i++) {
Item item = items[i];
if (item != null && item.cursed) {
item.cursed = false;
procced = true;
}
}
if (procced) {
hero.sprite.emitter().start( ShadowParticle.UP, 0.05f, 10 );
}
return procced;
}
@Override
public int price() {
return isKnown() ? 30 * quantity : super.price();
}
}
@@ -0,0 +1,91 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class ScrollOfTeleportation extends Scroll {
public static final String TXT_TELEPORTED =
"In a blink of an eye you were teleported to another location of the level.";
public static final String TXT_NO_TELEPORT =
"Strong magic aura of this place prevents you from teleporting!";
{
name = "Scroll of Teleportation";
}
@Override
protected void doRead() {
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
teleportHero( curUser );
setKnown();
curUser.spendAndNext( TIME_TO_READ );
}
public static void teleportHero( Hero hero ) {
int count = 10;
int pos;
do {
pos = Dungeon.level.randomRespawnCell();
if (count-- <= 0) {
break;
}
} while (pos == -1);
if (pos == -1) {
GLog.w( TXT_NO_TELEPORT );
} else {
WandOfBlink.appear( hero, pos );
Dungeon.level.press( pos, hero );
Dungeon.observe();
GLog.i( TXT_TELEPORTED );
}
}
@Override
public String desc() {
return
"The spell on this parchment instantly transports the reader " +
"to a random location on the dungeon level. It can be used " +
"to escape a dangerous situation, but the unlucky reader might " +
"find himself in an even more dangerous place.";
}
@Override
public int price() {
return isKnown() ? 40 * quantity : super.price();
}
}
@@ -0,0 +1,82 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class ScrollOfTerror extends Scroll {
{
name = "Scroll of Terror";
}
@Override
protected void doRead() {
new Flare( 5, 32 ).color( 0xFF0000, true ).show( curUser.sprite, 2f );
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
int count = 0;
Mob affected = null;
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (Level.fieldOfView[mob.pos]) {
Terror terror = Buff.affect( mob, Terror.class, Terror.DURATION );
terror.source = curUser;
count++;
affected = mob;
}
}
switch (count) {
case 0:
GLog.i( "The scroll emits a brilliant flash of red light" );
break;
case 1:
GLog.i( "The scroll emits a brilliant flash of red light and the " + affected.name + " flees!" );
break;
default:
GLog.i( "The scroll emits a brilliant flash of red light and the monsters flee!" );
}
setKnown();
curUser.spendAndNext( TIME_TO_READ );
}
@Override
public String desc() {
return
"A flash of red light will overwhelm all creatures in your field of view with terror, " +
"and they will turn and flee. Attacking a fleeing enemy will dispel the effect.";
}
@Override
public int price() {
return isKnown() ? 50 * quantity : super.price();
}
}
@@ -0,0 +1,64 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
public class ScrollOfUpgrade extends InventoryScroll {
private static final String TXT_LOOKS_BETTER = "your %s certainly looks better now";
{
name = "Scroll of Upgrade";
inventoryTitle = "Select an item to upgrade";
mode = WndBag.Mode.UPGRADEABLE;
}
@Override
protected void onItemSelected( Item item ) {
ScrollOfRemoveCurse.uncurse( Dungeon.hero, item );
item.upgrade();
GLog.p( TXT_LOOKS_BETTER, item.name() );
Badges.validateItemLevelAquired( item );
upgrade( curUser );
}
public static void upgrade( Hero hero ) {
hero.sprite.emitter().start( Speck.factory( Speck.UP ), 0.2f, 3 );
}
@Override
public String desc() {
return
"This scroll will upgrade a single item, improving its quality. A wand will " +
"increase in power and in number of charges; a weapon will inflict more damage " +
"or find its mark more frequently; a suit of armor will deflect additional blows; " +
"the effect of a ring on its wearer will intensify. Weapons and armor will also " +
"require less strength to use, and any curses on the item will be lifted.";
}
}
@@ -0,0 +1,60 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
public class ScrollOfWeaponUpgrade extends InventoryScroll {
private static final String TXT_LOOKS_BETTER = "your %s certainly looks better now";
{
name = "Scroll of Weapon Upgrade";
inventoryTitle = "Select a weapon to upgrade";
mode = WndBag.Mode.WEAPON;
}
@Override
protected void onItemSelected( Item item ) {
Weapon weapon = (Weapon)item;
ScrollOfRemoveCurse.uncurse( Dungeon.hero, weapon );
weapon.upgrade( true );
GLog.p( TXT_LOOKS_BETTER, weapon.name() );
Badges.validateItemLevelAquired( weapon );
curUser.sprite.emitter().start( Speck.factory( Speck.UP ), 0.2f, 3 );
}
@Override
public String desc() {
return
"This scroll will upgrade a melee weapon, improving its quality. In contrast to a regular Scroll of Upgrade, " +
"this specialized version will never destroy an enchantment on a weapon. On the contrary, it is able to imbue " +
"an unenchanted weapon with a random enchantment.";
}
}
@@ -0,0 +1,475 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.wands;
import java.util.ArrayList;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.ItemStatusHandler;
import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfPower.Power;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlot;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
public abstract class Wand extends KindOfWeapon {
public static final String AC_ZAP = "ZAP";
private static final String TXT_WOOD = "This thin %s wand is warm to the touch. Who knows what it will do when used?";
private static final String TXT_DAMAGE = "When this wand is used as a melee weapon, its average damage is %d points per hit.";
private static final String TXT_WEAPON = "You can use this wand as a melee weapon.";
private static final String TXT_FIZZLES = "your wand fizzles; it must be out of charges for now";
private static final String TXT_SELF_TARGET = "You can't target yourself";
private static final float TIME_TO_ZAP = 1f;
public int maxCharges = initialCharges();
public int curCharges = maxCharges;
protected Charger charger;
private boolean curChargeKnown = false;
protected boolean hitChars = true;
private static final Class<?>[] wands = {
WandOfTeleportation.class,
WandOfSlowness.class,
WandOfFirebolt.class,
WandOfPoison.class,
WandOfRegrowth.class,
WandOfBlink.class,
WandOfLightning.class,
WandOfAmok.class,
WandOfTelekinesis.class,
WandOfFlock.class,
WandOfDisintegration.class,
WandOfAvalanche.class
};
private static final String[] woods =
{"holly", "yew", "ebony", "cherry", "teak", "rowan", "willow", "mahogany", "bamboo", "purpleheart", "oak", "birch"};
private static final Integer[] images = {
ItemSpriteSheet.WAND_HOLLY,
ItemSpriteSheet.WAND_YEW,
ItemSpriteSheet.WAND_EBONY,
ItemSpriteSheet.WAND_CHERRY,
ItemSpriteSheet.WAND_TEAK,
ItemSpriteSheet.WAND_ROWAN,
ItemSpriteSheet.WAND_WILLOW,
ItemSpriteSheet.WAND_MAHOGANY,
ItemSpriteSheet.WAND_BAMBOO,
ItemSpriteSheet.WAND_PURPLEHEART,
ItemSpriteSheet.WAND_OAK,
ItemSpriteSheet.WAND_BIRCH};
private static ItemStatusHandler<Wand> handler;
private String wood;
{
defaultAction = AC_ZAP;
}
@SuppressWarnings("unchecked")
public static void initWoods() {
handler = new ItemStatusHandler<Wand>( (Class<? extends Wand>[])wands, woods, images );
}
public static void save( Bundle bundle ) {
handler.save( bundle );
}
@SuppressWarnings("unchecked")
public static void restore( Bundle bundle ) {
handler = new ItemStatusHandler<Wand>( (Class<? extends Wand>[])wands, woods, images, bundle );
}
public Wand() {
super();
calculateDamage();
try {
image = handler.image( this );
wood = handler.label( this );
} catch (Exception e) {
// Wand of Magic Missile
}
}
@Override
public ArrayList<String> actions( Hero hero ) {
ArrayList<String> actions = super.actions( hero );
if (curCharges > 0 || !curChargeKnown) {
actions.add( AC_ZAP );
}
if (hero.heroClass != HeroClass.MAGE) {
actions.remove( AC_EQUIP );
actions.remove( AC_UNEQUIP );
}
return actions;
}
@Override
public boolean doUnequip( Hero hero, boolean collect ) {
charger.detach();
return super.doUnequip(hero, collect);
}
@Override
public void activate( Hero hero ) {
charge( hero );
}
@Override
public void execute( Hero hero, String action ) {
if (action.equals( AC_ZAP )) {
curUser = hero;
curItem = this;
GameScene.selectCell( zapper );
} else {
super.execute( hero, action );
}
}
protected abstract void onZap( int cell );
@Override
public boolean collect( Bag container ) {
if (super.collect( container )) {
if (container.owner != null) {
charge( container.owner );
}
return true;
} else {
return false;
}
};
public void charge( Char owner ) {
(charger = new Charger()).attachTo( owner );
}
@Override
public Item detach( Bag container ) {
stopCharging();
return super.detach( container );
}
public void stopCharging() {
if (charger != null) {
charger.detach();
charger = null;
}
}
public int level() {
if (charger != null) {
Power power = charger.target.buff( Power.class );
return power == null ? level : Math.max( level + power.level, 0 );
} else {
return level;
}
}
protected boolean isKnown() {
return handler.isKnown( this );
}
public void setKnown() {
if (!isKnown()) {
handler.know( this );
}
Badges.validateAllWandsIdentified();
}
@Override
public Item identify() {
setKnown();
curChargeKnown = true;
super.identify();
updateQuickslot();
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder( super.toString() );
String status = status();
if (status != null) {
sb.append( " (" + status + ")" );
}
return sb.toString();
}
@Override
public String name() {
return isKnown() ? name : wood + " wand";
}
@Override
public String info() {
StringBuilder info = new StringBuilder( isKnown() ? desc() : String.format( TXT_WOOD, wood ) );
if (Dungeon.hero.heroClass == HeroClass.MAGE) {
info.append( "\n\n" );
if (levelKnown) {
info.append( String.format( TXT_DAMAGE, MIN + (MAX - MIN) / 2 ) );
} else {
info.append( String.format( TXT_WEAPON ) );
}
}
return info.toString();
}
@Override
public boolean isIdentified() {
return super.isIdentified() && isKnown() && curChargeKnown;
}
@Override
public String status() {
if (levelKnown) {
return (curChargeKnown ? curCharges : "?") + "/" + maxCharges;
} else {
return null;
}
}
@Override
public Item upgrade() {
super.upgrade();
updateLevel();
curCharges = Math.min( curCharges + 1, maxCharges );
updateQuickslot();
return this;
}
@Override
public Item degrade() {
super.degrade();
updateLevel();
updateQuickslot();
return this;
}
protected void updateLevel() {
maxCharges = Math.min( initialCharges() + level, 9 );
curCharges = Math.min( curCharges, maxCharges );
calculateDamage();
}
protected int initialCharges() {
return 2;
}
private void calculateDamage() {
int tier = 1 + level / 3;
MIN = tier;
MAX = (tier * tier - tier + 10) / 2 + level;
}
protected void fx( int cell, Callback callback ) {
MagicMissile.blueLight( curUser.sprite.parent, curUser.pos, cell, callback );
Sample.INSTANCE.play( Assets.SND_ZAP );
}
protected void wandUsed() {
curCharges--;
updateQuickslot();
curUser.spendAndNext( TIME_TO_ZAP );
}
@Override
public Item random() {
if (Random.Float() < 0.5f) {
upgrade();
if (Random.Float() < 0.15f) {
upgrade();
}
}
return this;
}
public static boolean allKnown() {
return handler.known().size() == wands.length;
}
@Override
public int price() {
int price = 50;
if (cursed && cursedKnown) {
price /= 2;
}
if (levelKnown) {
if (level > 0) {
price *= (level + 1);
} else if (level < 0) {
price /= (1 - level);
}
}
if (price < 1) {
price = 1;
}
return price;
}
private static final String MAX_CHARGES = "maxCharges";
private static final String CUR_CHARGES = "curCharges";
private static final String CUR_CHARGE_KNOWN = "curChargeKnown";
@Override
public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle );
bundle.put( MAX_CHARGES, maxCharges );
bundle.put( CUR_CHARGES, curCharges );
bundle.put( CUR_CHARGE_KNOWN, curChargeKnown );
}
@Override
public void restoreFromBundle( Bundle bundle ) {
super.restoreFromBundle( bundle );
maxCharges = bundle.getInt( MAX_CHARGES );
curCharges = bundle.getInt( CUR_CHARGES );
curChargeKnown = bundle.getBoolean( CUR_CHARGE_KNOWN );
}
protected static CellSelector.Listener zapper = new CellSelector.Listener() {
@Override
public void onSelect( Integer target ) {
if (target != null) {
if (target == curUser.pos) {
GLog.i( TXT_SELF_TARGET );
return;
}
final Wand curWand = (Wand)Wand.curItem;
curWand.setKnown();
final int cell = Ballistica.cast( curUser.pos, target, true, curWand.hitChars );
curUser.sprite.zap( cell );
QuickSlot.target( curItem, Actor.findChar( cell ) );
if (curWand.curCharges > 0) {
curUser.busy();
curWand.fx( cell, new Callback() {
@Override
public void call() {
curWand.onZap( cell );
curWand.wandUsed();
}
} );
Invisibility.dispel();
} else {
curUser.spendAndNext( TIME_TO_ZAP );
GLog.w( TXT_FIZZLES );
curWand.levelKnown = true;
curWand.updateQuickslot();
}
}
}
@Override
public String prompt() {
return "Choose direction to zap";
}
};
protected class Charger extends Buff {
private static final float TIME_TO_CHARGE = 40f;
@Override
public boolean attachTo( Char target ) {
super.attachTo( target );
delay();
return true;
}
@Override
public boolean act() {
if (curCharges < maxCharges) {
curCharges++;
updateQuickslot();
}
delay();
return true;
}
protected void delay() {
float time2charge = ((Hero)target).heroClass == HeroClass.MAGE ?
TIME_TO_CHARGE / (float)Math.sqrt( 1 + level ) :
TIME_TO_CHARGE;
spend( time2charge );
}
}
}
@@ -0,0 +1,61 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.wands;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Callback;
public class WandOfAmok extends Wand {
{
name = "Wand of Amok";
}
@Override
protected void onZap( int cell ) {
Char ch = Actor.findChar( cell );
if (ch != null) {
Buff.affect( ch, Amok.class, 3f + level() );
} else {
GLog.i( "nothing happened" );
}
}
protected void fx( int cell, Callback callback ) {
MagicMissile.purpleLight( curUser.sprite.parent, curUser.pos, cell, callback );
Sample.INSTANCE.play( Assets.SND_ZAP );
}
@Override
public String desc() {
return
"The purple light from this wand will make the target run amok " +
"attacking random creatures in its vicinity.";
}
}
@@ -0,0 +1,100 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.wands;
import com.watabou.noosa.Camera;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.watabou.utils.Callback;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
public class WandOfAvalanche extends Wand {
{
name = "Wand of Avalanche";
hitChars = false;
}
@Override
protected void onZap( int cell ) {
Sample.INSTANCE.play( Assets.SND_ROCKS );
int level = level();
Ballistica.distance = Math.min( Ballistica.distance, 8 + level );
int size = 1 + level / 3;
PathFinder.buildDistanceMap( cell, BArray.not( Level.solid, null ), size );
for (int i=0; i < Level.LENGTH; i++) {
int d = PathFinder.distance[i];
if (d < Integer.MAX_VALUE) {
Char ch = Actor.findChar( i );
if (ch != null) {
ch.sprite.flash();
ch.damage( Random.Int( 2, 6 + (size - d) * 2 ), this );
if (ch.isAlive() && Random.Int( 2 + d ) == 0) {
Buff.prolong( ch, Paralysis.class, Random.IntRange( 2, 6 ) );
}
}
CellEmitter.get( i ).start( Speck.factory( Speck.ROCK ), 0.07f, 3 + (size - d) );
Camera.main.shake( 3, 0.07f * (3 + (size - d)) );
}
}
if (!curUser.isAlive()) {
Dungeon.fail( Utils.format( ResultDescriptions.WAND, name, Dungeon.depth ) );
GLog.n( "You killed yourself with your own Wand of Avalanche..." );
}
}
protected void fx( int cell, Callback callback ) {
MagicMissile.earth( curUser.sprite.parent, curUser.pos, cell, callback );
Sample.INSTANCE.play( Assets.SND_ZAP );
}
@Override
public String desc() {
return
"When a discharge of this wand hits a wall (or any other solid obstacle) it causes " +
"an avalanche of stones, damaging and stunning all creatures in the affected area.";
}
}

Some files were not shown because too many files have changed in this diff Show More