v0.3.0: added Ethereal Chains
This commit is contained in:
parent
fc6d1f128b
commit
febcd8d840
Binary file not shown.
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
@ -65,6 +65,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Viscosity;
|
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Viscosity;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CapeOfThorns;
|
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CapeOfThorns;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
|
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.EtherealChains;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight;
|
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass;
|
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.GoldenKey;
|
import com.shatteredpixel.shatteredpixeldungeon.items.keys.GoldenKey;
|
||||||
|
@ -1092,10 +1093,13 @@ public class Hero extends Char {
|
||||||
public void earnExp( int exp ) {
|
public void earnExp( int exp ) {
|
||||||
|
|
||||||
this.exp += exp;
|
this.exp += exp;
|
||||||
|
float percent = exp/(float)maxExp();
|
||||||
|
|
||||||
|
EtherealChains.chainsRecharge chains = buff(EtherealChains.chainsRecharge.class);
|
||||||
|
if (chains != null) chains.gainExp(percent);
|
||||||
|
|
||||||
if (subClass == HeroSubClass.WARLOCK) {
|
if (subClass == HeroSubClass.WARLOCK) {
|
||||||
|
|
||||||
float percent = exp/(float)maxExp();
|
|
||||||
int healed = Math.round(Math.min(HT - HP, HT * percent * 0.3f));
|
int healed = Math.round(Math.min(HT - HP, HT * percent * 0.3f));
|
||||||
if (healed > 0) {
|
if (healed > 0) {
|
||||||
HP += healed;
|
HP += healed;
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.effects;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap;
|
||||||
|
import com.watabou.noosa.Game;
|
||||||
|
import com.watabou.noosa.Group;
|
||||||
|
import com.watabou.noosa.Image;
|
||||||
|
import com.watabou.utils.Callback;
|
||||||
|
import com.watabou.utils.PointF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Evan on 23/05/2015.
|
||||||
|
*/
|
||||||
|
public class Chains extends Group {
|
||||||
|
|
||||||
|
private static final double A = 180 / Math.PI;
|
||||||
|
|
||||||
|
private float spent = 0f;
|
||||||
|
private float duration;
|
||||||
|
|
||||||
|
private Callback callback;
|
||||||
|
|
||||||
|
private Image[] chains;
|
||||||
|
private int numChains;
|
||||||
|
private float distance;
|
||||||
|
private float rotation = 0;
|
||||||
|
|
||||||
|
private PointF from, to;
|
||||||
|
|
||||||
|
public Chains(int from, int to, Callback callback){
|
||||||
|
this(DungeonTilemap.tileCenterToWorld(from),
|
||||||
|
DungeonTilemap.tileCenterToWorld(to),
|
||||||
|
callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chains(PointF from, PointF to, Callback callback){
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.callback = callback;
|
||||||
|
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
|
||||||
|
float dx = to.x - from.x;
|
||||||
|
float dy = to.y - from.y;
|
||||||
|
distance = (float)Math.hypot(dx, dy);
|
||||||
|
|
||||||
|
|
||||||
|
duration = distance/300f + 0.1f;
|
||||||
|
|
||||||
|
rotation = (float)(Math.atan2( dy, dx ) * A) + 90f;
|
||||||
|
|
||||||
|
numChains = Math.round(distance/6f)+1;
|
||||||
|
|
||||||
|
chains = new Image[numChains];
|
||||||
|
for (int i = 0; i < chains.length; i++){
|
||||||
|
chains[i] = new Image(Effects.get(Effects.Type.CHAIN));
|
||||||
|
chains[i].angle = rotation;
|
||||||
|
chains[i].origin.set( chains[i].width()/ 2, chains[i].height() );
|
||||||
|
add(chains[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
if ((spent += Game.elapsed) > duration) {
|
||||||
|
|
||||||
|
killAndErase();
|
||||||
|
if (callback != null) {
|
||||||
|
callback.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
float dx = to.x - from.x;
|
||||||
|
float dy = to.y - from.y;
|
||||||
|
for (int i = 0; i < chains.length; i++) {
|
||||||
|
chains[i].center(new PointF(
|
||||||
|
from.x + ((dx * (i / (float)chains.length)) * (spent/duration)),
|
||||||
|
from.y + ((dy * (i / (float)chains.length)) * (spent/duration))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ public class Effects {
|
||||||
LIGHTNING,
|
LIGHTNING,
|
||||||
WOUND,
|
WOUND,
|
||||||
EXCLAMATION,
|
EXCLAMATION,
|
||||||
|
CHAIN,
|
||||||
DEATH_RAY,
|
DEATH_RAY,
|
||||||
LIGHT_RAY,
|
LIGHT_RAY,
|
||||||
HEALTH_RAY
|
HEALTH_RAY
|
||||||
|
@ -47,6 +48,9 @@ public class Effects {
|
||||||
case EXCLAMATION:
|
case EXCLAMATION:
|
||||||
icon.frame(icon.texture.uvRect(0, 16, 6, 25));
|
icon.frame(icon.texture.uvRect(0, 16, 6, 25));
|
||||||
break;
|
break;
|
||||||
|
case CHAIN:
|
||||||
|
icon.frame(icon.texture.uvRect(6, 16, 11, 22));
|
||||||
|
break;
|
||||||
case DEATH_RAY:
|
case DEATH_RAY:
|
||||||
icon.frame(icon.texture.uvRect(16, 16, 32, 24));
|
icon.frame(icon.texture.uvRect(16, 16, 32, 24));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -193,10 +193,10 @@ public class Generator {
|
||||||
UnstableSpellbook.class,
|
UnstableSpellbook.class,
|
||||||
AlchemistsToolkit.class, //currently removed from drop tables, pending rework.
|
AlchemistsToolkit.class, //currently removed from drop tables, pending rework.
|
||||||
DriedRose.class, //starts with no chance of spawning, chance is set directly after beating ghost quest.
|
DriedRose.class, //starts with no chance of spawning, chance is set directly after beating ghost quest.
|
||||||
LloydsBeacon.class
|
LloydsBeacon.class,
|
||||||
/*EtherealChains.class*/
|
EtherealChains.class
|
||||||
};
|
};
|
||||||
Category.ARTIFACT.probs = new float[]{ 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0 /*, 1*/};
|
Category.ARTIFACT.probs = new float[]{ 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0 , 1};
|
||||||
|
|
||||||
Category.SEED.classes = new Class<?>[]{
|
Category.SEED.classes = new Class<?>[]{
|
||||||
Firebloom.Seed.class,
|
Firebloom.Seed.class,
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
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.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.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 java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Evan on 23/05/2015.
|
||||||
|
*/
|
||||||
|
public class EtherealChains extends Artifact {
|
||||||
|
|
||||||
|
public static final String AC_CAST = "CAST";
|
||||||
|
|
||||||
|
{
|
||||||
|
name = "ethereal chains";
|
||||||
|
image = ItemSpriteSheet.ARTIFACT_CHAINS;
|
||||||
|
|
||||||
|
level = 0;
|
||||||
|
levelCap = 5;
|
||||||
|
exp = 0;
|
||||||
|
|
||||||
|
charge = 0;
|
||||||
|
|
||||||
|
defaultAction = AC_CAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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("You need to equip the chains to do that.");
|
||||||
|
else if (charge < 1) GLog.i("Your chains do not have any available charge.");
|
||||||
|
else if (cursed) GLog.w("You can't use cursed chains.");
|
||||||
|
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])){
|
||||||
|
final Ballistica chain = new Ballistica(curUser.pos, target, Ballistica.STOP_CHARS | Ballistica.STOP_TARGET);
|
||||||
|
|
||||||
|
//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("That won't do anything");
|
||||||
|
} else {
|
||||||
|
final int newMobPos = newPos;
|
||||||
|
final Char affected = Actor.findChar( chain.collisionPos );
|
||||||
|
int chargeUse = Level.distance(affected.pos, newMobPos);
|
||||||
|
if (chargeUse > charge){
|
||||||
|
GLog.w("Your chains do not have enough charge.");
|
||||||
|
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));
|
||||||
|
affected.pos = newMobPos;
|
||||||
|
Dungeon.observe();
|
||||||
|
curUser.spendAndNext(1f);
|
||||||
|
Dungeon.level.press(newMobPos, affected);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
} 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("That won't do anything");
|
||||||
|
} else {
|
||||||
|
final int newHeroPos = newPos;
|
||||||
|
int chargeUse = Level.distance(curUser.pos, newHeroPos);
|
||||||
|
if (chargeUse > charge){
|
||||||
|
GLog.w("Your chains do not have enough 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));
|
||||||
|
curUser.pos = newHeroPos;
|
||||||
|
Dungeon.observe();
|
||||||
|
curUser.spendAndNext(1f);
|
||||||
|
Dungeon.level.press(newHeroPos, curUser);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
GLog.i("There is nothing to grab there");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String prompt() {
|
||||||
|
return "Choose a location to target";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ArtifactBuff passiveBuff() {
|
||||||
|
return new chainsRecharge();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: description
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return super.desc();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class chainsRecharge extends ArtifactBuff{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean act() {
|
||||||
|
int chargeTarget = 5+level;
|
||||||
|
if (charge < chargeTarget) {
|
||||||
|
partialCharge += 1 / (40f - (chargeTarget - charge)*3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partialCharge >= 1) {
|
||||||
|
partialCharge --;
|
||||||
|
charge ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateQuickslot();
|
||||||
|
|
||||||
|
spend( TICK );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gainExp( float levelPortion ) {
|
||||||
|
exp += Math.round(levelPortion*100);
|
||||||
|
partialCharge += levelPortion*10f;
|
||||||
|
|
||||||
|
if (exp > 100+level*50){
|
||||||
|
exp -= 100+level*50;
|
||||||
|
GLog.p("Your chains grow stronger!");
|
||||||
|
upgrade();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user