Magic_Ling_Pixel_Dungeon/src/com/shatteredpixel/shatteredpixeldungeon/items/Item.java

468 lines
11 KiB
Java
Raw Normal View History

2014-07-27 13:39:07 +00:00
/*
* 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;
2014-07-27 13:39:07 +00:00
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;
2014-07-27 13:39:07 +00:00
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";
public int image = 0;
2014-07-27 13:39:07 +00:00
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 );
}
2014-10-21 04:38:15 +00:00
public final Item detach( Bag container ) {
2014-07-27 13:39:07 +00:00
if (quantity <= 0) {
return null;
} else
if (quantity == 1) {
return detachAll( container );
} else {
quantity--;
updateQuickslot();
2014-10-21 04:38:15 +00:00
try {
Item detached = getClass().newInstance();
detached.onDetach( );
return detached;
2014-07-27 13:39:07 +00:00
} catch (Exception e) {
return null;
}
}
}
2014-10-21 04:38:15 +00:00
public final Item detachAll( Bag container ) {
for (Item item : container.items) {
if (item == this) {
container.items.remove( this );
item.onDetach( );
QuickSlot.refresh();
return this;
} else if (item instanceof Bag) {
Bag bag = (Bag)item;
if (bag.contains( this )) {
return detachAll( bag );
}
}
}
2014-07-27 13:39:07 +00:00
return this;
}
public boolean isSimilar( Item item ) {
return getClass() == item.getClass();
}
2014-10-21 04:38:15 +00:00
protected void onDetach(){}
2014-07-27 13:39:07 +00:00
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) {
2014-10-21 04:38:15 +00:00
// FIXME
2014-07-27 13:39:07 +00:00
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";
}
};
}