Files
shattered-pixel-dungeon-web…/src/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/EtherealChains.java
T
2016-02-22 16:48:24 -05:00

250 lines
7.6 KiB
Java

/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2015 Evan Debenham
*
* 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.artifacts;
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.Cripple;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Chains;
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
import java.util.ArrayList;
public class EtherealChains extends Artifact {
public static final String AC_CAST = "CAST";
{
image = ItemSpriteSheet.ARTIFACT_CHAINS;
levelCap = 5;
exp = 0;
charge = 5;
defaultAction = AC_CAST;
usesTargeting = true;
}
@Override
public ArrayList<String> actions(Hero hero) {
ArrayList<String> actions = super.actions( hero );
if (isEquipped(hero) && charge > 0 && !cursed)
actions.add(AC_CAST);
return actions;
}
@Override
public void execute(Hero hero, String action) {
if (action.equals(AC_CAST)){
curUser = hero;
if (!isEquipped( hero )) GLog.i( Messages.get(Artifact.class, "need_to_equip") );
else if (charge < 1) GLog.i( Messages.get(this, "no_charge") );
else if (cursed) GLog.w( Messages.get(this, "cursed") );
else {
GameScene.selectCell(caster);
}
} else
super.execute(hero, action);
}
private CellSelector.Listener caster = new CellSelector.Listener(){
@Override
public void onSelect(Integer target) {
if (target != null && (Dungeon.level.visited[target] || Dungeon.level.mapped[target])){
//ballistica does not go through walls on pre-rework boss arenas
int missileProperties = (Dungeon.depth == 10 || Dungeon.depth == 15 || Dungeon.depth == 20 || Dungeon.depth == 25) ?
Ballistica.PROJECTILE : Ballistica.STOP_CHARS | Ballistica.STOP_TARGET;
final Ballistica chain = new Ballistica(curUser.pos, target, missileProperties);
//determine if we're grabbing an enemy, pulling to a location, or doing nothing.
if (Actor.findChar( chain.collisionPos ) != null){
int newPos = -1;
for (int i : chain.subPath(1, chain.dist)){
if (!Level.solid[i] && Actor.findChar(i) == null){
newPos = i;
break;
}
}
if (newPos == -1){
GLog.w( Messages.get(EtherealChains.class, "does_nothing") );
} else {
final int newMobPos = newPos;
final Char affected = Actor.findChar( chain.collisionPos );
int chargeUse = Level.distance(affected.pos, newMobPos);
if (chargeUse > charge) {
GLog.w( Messages.get(EtherealChains.class, "no_charge") );
return;
} else if (affected.properties().contains(Char.Property.IMMOVABLE)) {
GLog.w( Messages.get(EtherealChains.class, "cant_pull") );
return;
} else {
charge -= chargeUse;
updateQuickslot();
}
curUser.busy();
curUser.sprite.parent.add(new Chains(curUser.pos, affected.pos, new Callback() {
public void call() {
Actor.add(new Pushing(affected, affected.pos, newMobPos, new Callback() {
public void call() {
Dungeon.level.press(newMobPos, affected);
}
}));
affected.pos = newMobPos;
Dungeon.observe();
curUser.spendAndNext(1f);
}
}));
}
} else if (Level.solid[chain.path.get(chain.dist)]
|| (chain.dist > 0 && Level.solid[chain.path.get(chain.dist-1)])
|| (chain.path.size() > chain.dist+1 && Level.solid[chain.path.get(chain.dist+1)])
//if the player is trying to grapple the edge of the map, let them.
|| (chain.path.size() == chain.dist+1)) {
int newPos = -1;
for (int i : chain.subPath(1, chain.dist)){
if (!Level.solid[i] && Actor.findChar(i) == null) newPos = i;
}
if (newPos == -1) {
GLog.w( Messages.get(EtherealChains.class, "does_nothing") );
} else {
final int newHeroPos = newPos;
int chargeUse = Level.distance(curUser.pos, newHeroPos);
if (chargeUse > charge){
GLog.w( Messages.get(EtherealChains.class, "no_charge") );
return;
} else {
charge -= chargeUse;
updateQuickslot();
}
curUser.busy();
curUser.sprite.parent.add(new Chains(curUser.pos, target, new Callback() {
public void call() {
Actor.add(new Pushing(curUser, curUser.pos, newHeroPos, new Callback() {
public void call() {
Dungeon.level.press(newHeroPos, curUser);
}
}));
curUser.spendAndNext(1f);
curUser.pos = newHeroPos;
Dungeon.observe();
}
}));
}
} else {
GLog.i( Messages.get(EtherealChains.class, "nothing_to_grab") );
}
}
}
@Override
public String prompt() {
return Messages.get(EtherealChains.class, "prompt");
}
};
@Override
protected ArtifactBuff passiveBuff() {
return new chainsRecharge();
}
@Override
public String desc() {
String desc = super.desc();
if (isEquipped( Dungeon.hero )){
desc += "\n\n";
if (cursed)
desc += Messages.get(this, "desc_cursed");
else
desc += Messages.get(this, "desc_equipped");
}
return desc;
}
public class chainsRecharge extends ArtifactBuff{
@Override
public boolean act() {
int chargeTarget = 5+(level()*2);
LockedFloor lock = target.buff(LockedFloor.class);
if (charge < chargeTarget && !cursed && (lock == null || lock.regenOn())) {
partialCharge += 1 / (40f - (chargeTarget - charge)*2f);
} else if (cursed && Random.Int(100) == 0){
Buff.prolong( target, Cripple.class, 10f);
}
if (partialCharge >= 1) {
partialCharge --;
charge ++;
}
updateQuickslot();
spend( TICK );
return true;
}
public void gainExp( float levelPortion ) {
if (cursed) return;
exp += Math.round(levelPortion*100);
//past the soft charge cap, gaining charge from leveling is slowed.
if (charge > 5+(level()*2)){
levelPortion *= (5+((float)level()*2))/charge;
}
partialCharge += levelPortion*10f;
if (exp > 100+level()*50 && level() < levelCap){
exp -= 100+level()*50;
GLog.p( Messages.get(this, "levelup") );
upgrade();
}
}
}
}