V0.1.0 Partial Commit
changed package and application names to differentiate from main PD release
This commit is contained in:
@@ -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";
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user