v0.7.4: initial implementation for wand of warding
This commit is contained in:
parent
b8490b5b29
commit
545cda0bba
BIN
core/src/main/assets/wards.png
Normal file
BIN
core/src/main/assets/wards.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 279 B |
|
@ -97,6 +97,7 @@ public class Assets {
|
||||||
public static final String ROT_LASH = "rot_lasher.png";
|
public static final String ROT_LASH = "rot_lasher.png";
|
||||||
public static final String ROT_HEART= "rot_heart.png";
|
public static final String ROT_HEART= "rot_heart.png";
|
||||||
public static final String GUARD = "guard.png";
|
public static final String GUARD = "guard.png";
|
||||||
|
public static final String WARDS = "wards.png";
|
||||||
|
|
||||||
public static final String ITEMS = "items.png";
|
public static final String ITEMS = "items.png";
|
||||||
public static final String TERRAIN_FEATURES = "terrain_features.png";
|
public static final String TERRAIN_FEATURES = "terrain_features.png";
|
||||||
|
|
|
@ -131,6 +131,10 @@ public abstract class Char extends Actor {
|
||||||
Dungeon.level.updateFieldOfView( this, fieldOfView );
|
Dungeon.level.updateFieldOfView( this, fieldOfView );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canInteract( Hero h ){
|
||||||
|
return Dungeon.level.adjacent( pos, h.pos );
|
||||||
|
}
|
||||||
|
|
||||||
//swaps places by default
|
//swaps places by default
|
||||||
public boolean interact(){
|
public boolean interact(){
|
||||||
|
|
|
@ -630,7 +630,7 @@ public class Hero extends Char {
|
||||||
|
|
||||||
Char ch = action.ch;
|
Char ch = action.ch;
|
||||||
|
|
||||||
if (Dungeon.level.adjacent( pos, ch.pos )) {
|
if (ch.canInteract(this)) {
|
||||||
|
|
||||||
ready();
|
ready();
|
||||||
sprite.turnTo( pos, ch.pos );
|
sprite.turnTo( pos, ch.pos );
|
||||||
|
|
|
@ -59,6 +59,7 @@ public class MagicMissile extends Emitter {
|
||||||
public static final int SHADOW = 7;
|
public static final int SHADOW = 7;
|
||||||
public static final int RAINBOW = 8;
|
public static final int RAINBOW = 8;
|
||||||
public static final int EARTH = 9;
|
public static final int EARTH = 9;
|
||||||
|
public static final int WARD = 10;
|
||||||
|
|
||||||
public static final int FIRE_CONE = 100;
|
public static final int FIRE_CONE = 100;
|
||||||
public static final int FOLIAGE_CONE = 101;
|
public static final int FOLIAGE_CONE = 101;
|
||||||
|
@ -138,6 +139,10 @@ public class MagicMissile extends Emitter {
|
||||||
size( 4 );
|
size( 4 );
|
||||||
pour( EarthParticle.FACTORY, 0.01f );
|
pour( EarthParticle.FACTORY, 0.01f );
|
||||||
break;
|
break;
|
||||||
|
case WARD:
|
||||||
|
size( 4 );
|
||||||
|
pour( WardParticle.FACTORY, 0.01f );
|
||||||
|
break;
|
||||||
|
|
||||||
case FIRE_CONE:
|
case FIRE_CONE:
|
||||||
size( 10 );
|
size( 10 );
|
||||||
|
@ -416,26 +421,37 @@ public class MagicMissile extends Emitter {
|
||||||
am = (1 - left / lifespan) / 2;
|
am = (1 - left / lifespan) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ColdParticle extends PixelParticle.Shrinking {
|
public static class WardParticle extends PixelParticle.Shrinking {
|
||||||
|
|
||||||
public static final Emitter.Factory FACTORY = new Factory() {
|
public static final Emitter.Factory FACTORY = new Factory() {
|
||||||
@Override
|
@Override
|
||||||
public void emit( Emitter emitter, int index, float x, float y ) {
|
public void emit( Emitter emitter, int index, float x, float y ) {
|
||||||
((ColdParticle)emitter.recycle( ColdParticle.class )).reset( x, y );
|
((WardParticle)emitter.recycle( WardParticle.class )).reset( x, y );
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean lightMode() {
|
public boolean lightMode() {
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final Emitter.Factory UP = new Factory() {
|
||||||
|
@Override
|
||||||
|
public void emit( Emitter emitter, int index, float x, float y ) {
|
||||||
|
((WardParticle)emitter.recycle( WardParticle.class )).resetUp( x, y );
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean lightMode() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public ColdParticle() {
|
public WardParticle() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
lifespan = 0.6f;
|
lifespan = 0.6f;
|
||||||
|
|
||||||
color( 0x2244FF );
|
color( 0x8822FF );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset( float x, float y ) {
|
public void reset( float x, float y ) {
|
||||||
|
@ -447,6 +463,12 @@ public class MagicMissile extends Emitter {
|
||||||
left = lifespan;
|
left = lifespan;
|
||||||
size = 8;
|
size = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resetUp( float x, float y){
|
||||||
|
reset(x, y);
|
||||||
|
|
||||||
|
speed.set( Random.Float( -8, +8 ), Random.Float( -32, -48 ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
|
|
|
@ -106,10 +106,12 @@ import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfDisintegration
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFrost;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFrost;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLightning;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLightning;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLivingEarth;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfPrismaticLight;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfPrismaticLight;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfTransfusion;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfTransfusion;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.AssassinsBlade;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.AssassinsBlade;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.BattleAxe;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.BattleAxe;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Crossbow;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Crossbow;
|
||||||
|
@ -296,8 +298,7 @@ public class Generator {
|
||||||
StoneOfShock.class
|
StoneOfShock.class
|
||||||
};
|
};
|
||||||
STONE.probs = new float[]{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
STONE.probs = new float[]{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||||
|
|
||||||
//TODO: add last ones when implemented
|
|
||||||
WAND.classes = new Class<?>[]{
|
WAND.classes = new Class<?>[]{
|
||||||
WandOfMagicMissile.class,
|
WandOfMagicMissile.class,
|
||||||
WandOfLightning.class,
|
WandOfLightning.class,
|
||||||
|
@ -305,14 +306,14 @@ public class Generator {
|
||||||
WandOfFireblast.class,
|
WandOfFireblast.class,
|
||||||
WandOfCorrosion.class,
|
WandOfCorrosion.class,
|
||||||
WandOfBlastWave.class,
|
WandOfBlastWave.class,
|
||||||
//WandOfLivingEarth.class,
|
WandOfLivingEarth.class,
|
||||||
WandOfFrost.class,
|
WandOfFrost.class,
|
||||||
WandOfPrismaticLight.class,
|
WandOfPrismaticLight.class,
|
||||||
//WandOfWarding.class,
|
WandOfWarding.class,
|
||||||
WandOfTransfusion.class,
|
WandOfTransfusion.class,
|
||||||
WandOfCorruption.class,
|
WandOfCorruption.class,
|
||||||
WandOfRegrowth.class };
|
WandOfRegrowth.class };
|
||||||
WAND.probs = new float[]{ 5, 4, 4, 4, 4, 3, /*3,*/ 3, 3, /*3,*/ 3, 3, 3 };
|
WAND.probs = new float[]{ 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||||
|
|
||||||
//see generator.randomWeapon
|
//see generator.randomWeapon
|
||||||
WEAPON.classes = new Class<?>[]{};
|
WEAPON.classes = new Class<?>[]{};
|
||||||
|
|
|
@ -111,6 +111,21 @@ public abstract class Wand extends Item {
|
||||||
|
|
||||||
public abstract void onHit( MagesStaff staff, Char attacker, Char defender, int damage);
|
public abstract void onHit( MagesStaff staff, Char attacker, Char defender, int damage);
|
||||||
|
|
||||||
|
public boolean tryToZap( Hero owner ){
|
||||||
|
|
||||||
|
if (owner.buff(MagicImmune.class) != null){
|
||||||
|
GLog.w( Messages.get(this, "no_magic") );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( curCharges >= (cursed ? 1 : chargesPerCast())){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
GLog.w(Messages.get(this, "fizzles"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean collect( Bag container ) {
|
public boolean collect( Bag container ) {
|
||||||
if (super.collect( container )) {
|
if (super.collect( container )) {
|
||||||
|
@ -411,9 +426,6 @@ public abstract class Wand extends Item {
|
||||||
if (target == curUser.pos || cell == curUser.pos) {
|
if (target == curUser.pos || cell == curUser.pos) {
|
||||||
GLog.i( Messages.get(Wand.class, "self_target") );
|
GLog.i( Messages.get(Wand.class, "self_target") );
|
||||||
return;
|
return;
|
||||||
} else if (curUser.buff(MagicImmune.class) != null){
|
|
||||||
GLog.w( Messages.get(Wand.class, "no_magic") );
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curUser.sprite.zap(cell);
|
curUser.sprite.zap(cell);
|
||||||
|
@ -424,7 +436,7 @@ public abstract class Wand extends Item {
|
||||||
else
|
else
|
||||||
QuickSlotButton.target(Actor.findChar(cell));
|
QuickSlotButton.target(Actor.findChar(cell));
|
||||||
|
|
||||||
if (curWand.curCharges >= (curWand.cursed ? 1 : curWand.chargesPerCast())) {
|
if (curWand.tryToZap(curUser)) {
|
||||||
|
|
||||||
curUser.busy();
|
curUser.busy();
|
||||||
Invisibility.dispel();
|
Invisibility.dispel();
|
||||||
|
@ -452,10 +464,6 @@ public abstract class Wand extends Item {
|
||||||
}
|
}
|
||||||
curWand.cursedKnown = true;
|
curWand.cursedKnown = true;
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
GLog.w( Messages.get(Wand.class, "fizzles") );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,329 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.items.wands;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
|
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.actors.mobs.npcs.NPC;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.WardSprite;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
|
||||||
|
import com.watabou.noosa.audio.Sample;
|
||||||
|
import com.watabou.utils.Bundle;
|
||||||
|
import com.watabou.utils.Callback;
|
||||||
|
import com.watabou.utils.PathFinder;
|
||||||
|
import com.watabou.utils.Random;
|
||||||
|
|
||||||
|
public class WandOfWarding extends Wand {
|
||||||
|
|
||||||
|
{
|
||||||
|
collisionProperties = Ballistica.STOP_TARGET | Ballistica.STOP_TERRAIN;
|
||||||
|
|
||||||
|
image = ItemSpriteSheet.WAND_WARDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onZap(Ballistica bolt) {
|
||||||
|
|
||||||
|
int currentWardLevels = 0;
|
||||||
|
for (Char ch : Actor.chars()){
|
||||||
|
if (ch instanceof Ward){
|
||||||
|
currentWardLevels += ((Ward) ch).tier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean canPlaceMore = currentWardLevels < level()+2;
|
||||||
|
|
||||||
|
Char ch = Actor.findChar(bolt.collisionPos);
|
||||||
|
if (ch != null){
|
||||||
|
if (ch instanceof Ward){
|
||||||
|
if (canPlaceMore) {
|
||||||
|
((Ward) ch).upgrade(level());
|
||||||
|
} else {
|
||||||
|
if (((Ward) ch).tier <= 3){
|
||||||
|
GLog.w("Your wand can't sustain any more wards.");
|
||||||
|
} else {
|
||||||
|
((Ward) ch).wandHeal( level() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ch.sprite.emitter().burst(MagicMissile.WardParticle.UP, ((Ward) ch).tier);
|
||||||
|
} else {
|
||||||
|
GLog.w("There isn't room to place a ward here");
|
||||||
|
}
|
||||||
|
} else if (canPlaceWard(bolt.collisionPos)){
|
||||||
|
if (canPlaceMore) {
|
||||||
|
Ward ward = new Ward();
|
||||||
|
ward.pos = bolt.collisionPos;
|
||||||
|
GameScene.add(ward, 1f);
|
||||||
|
ward.sprite.emitter().burst(MagicMissile.WardParticle.UP, ward.tier);
|
||||||
|
QuickSlotButton.target(ward);
|
||||||
|
} else {
|
||||||
|
GLog.w("Your wand can't sustain any more wards.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GLog.w("There isn't room to place a ward here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fx(Ballistica bolt, Callback callback) {
|
||||||
|
MagicMissile.boltFromChar(curUser.sprite.parent,
|
||||||
|
MagicMissile.WARD,
|
||||||
|
curUser.sprite,
|
||||||
|
bolt.collisionPos,
|
||||||
|
callback);
|
||||||
|
Sample.INSTANCE.play(Assets.SND_ZAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void staffFx(MagesStaff.StaffParticle particle) {
|
||||||
|
//TODO
|
||||||
|
super.staffFx(particle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canPlaceWard(int pos){
|
||||||
|
|
||||||
|
int adjacentBlockedCells = 0;
|
||||||
|
int adjacentCellGroups = 0;
|
||||||
|
boolean prevOpen = openCell(pos + PathFinder.CIRCLE8[PathFinder.CIRCLE8.length-1]);
|
||||||
|
|
||||||
|
for (int i : PathFinder.CIRCLE8){
|
||||||
|
if (!openCell(pos + i)){
|
||||||
|
adjacentBlockedCells++;
|
||||||
|
}
|
||||||
|
if (prevOpen != openCell(pos + i)){
|
||||||
|
prevOpen = !prevOpen;
|
||||||
|
adjacentCellGroups++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adjacentBlockedCells){
|
||||||
|
case 0: case 1:
|
||||||
|
return true;
|
||||||
|
case 2:
|
||||||
|
return (openCell(pos + PathFinder.CIRCLE4[0]) || openCell( pos + PathFinder.CIRCLE4[2]))
|
||||||
|
&& (openCell(pos + PathFinder.CIRCLE4[1]) || openCell( pos + PathFinder.CIRCLE4[3]));
|
||||||
|
case 3:
|
||||||
|
return adjacentCellGroups <= 2;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean openCell(int pos){
|
||||||
|
//a cell is considered blocked if it isn't passable or a ward is there
|
||||||
|
return Dungeon.level.passable[pos] && !(Actor.findChar(pos) instanceof Ward);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Ward extends NPC {
|
||||||
|
|
||||||
|
private int tier = 1;
|
||||||
|
private int wandLevel = 1;
|
||||||
|
|
||||||
|
private int totalZaps = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
spriteClass = WardSprite.class;
|
||||||
|
|
||||||
|
alignment = Alignment.ALLY;
|
||||||
|
|
||||||
|
properties.add(Property.IMMOVABLE);
|
||||||
|
|
||||||
|
viewDistance = 3;
|
||||||
|
state = WANDERING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void upgrade( int wandLevel ){
|
||||||
|
if (this.wandLevel < wandLevel){
|
||||||
|
this.wandLevel = wandLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
wandHeal(0);
|
||||||
|
|
||||||
|
switch (tier){
|
||||||
|
case 1: case 2: default:
|
||||||
|
break; //do nothing
|
||||||
|
case 3:
|
||||||
|
HP = HT = 30;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
HT = 48;
|
||||||
|
HP = Math.round(48*(HP/30f));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
HT = 72;
|
||||||
|
HP = Math.round(72*(HP/48f));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tier < 6){
|
||||||
|
tier++;
|
||||||
|
viewDistance++;
|
||||||
|
updateSpriteState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void wandHeal( int wandLevel ){
|
||||||
|
if (this.wandLevel < wandLevel){
|
||||||
|
this.wandLevel = wandLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(tier){
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
HP = Math.min(HT, HP+6);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
HP = Math.min(HT, HP+8);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
HP = Math.min(HT, HP+12);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float attackDelay() {
|
||||||
|
switch (tier){
|
||||||
|
case 1: case 2: default:
|
||||||
|
return 2f;
|
||||||
|
case 3: case 4:
|
||||||
|
return 1.5f;
|
||||||
|
case 5: case 6:
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canAttack( Char enemy ) {
|
||||||
|
return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean doAttack(Char enemy) {
|
||||||
|
boolean visible = fieldOfView[pos] || fieldOfView[enemy.pos];
|
||||||
|
if (visible) {
|
||||||
|
sprite.zap( enemy.pos );
|
||||||
|
} else {
|
||||||
|
zap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return !visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zap() {
|
||||||
|
spend( 1f );
|
||||||
|
|
||||||
|
//always hits
|
||||||
|
int dmg = Random.Int( 2 + wandLevel, 8 + 4*wandLevel );
|
||||||
|
enemy.damage( dmg, WandOfWarding.class );
|
||||||
|
|
||||||
|
if (!enemy.isAlive() && enemy == Dungeon.hero) {
|
||||||
|
Dungeon.fail( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
totalZaps++;
|
||||||
|
switch(tier){
|
||||||
|
default:
|
||||||
|
if (totalZaps >= tier){
|
||||||
|
die(this);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (totalZaps >= 4){
|
||||||
|
die(this);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
damage(6, this);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
damage(8, this);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
damage(9, this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onZapComplete() {
|
||||||
|
zap();
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean getCloser(int target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean getFurther(int target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSprite sprite() {
|
||||||
|
WardSprite sprite = (WardSprite) super.sprite();
|
||||||
|
sprite.updateTier(tier);
|
||||||
|
return sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSpriteState() {
|
||||||
|
super.updateSpriteState();
|
||||||
|
((WardSprite)sprite).updateTier(tier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canInteract(Hero h) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean interact() {
|
||||||
|
GameScene.show(new WndOptions("test", "dismiss this ward?", "yes", "no"){
|
||||||
|
@Override
|
||||||
|
protected void onSelect(int index) {
|
||||||
|
if (index == 0){
|
||||||
|
die(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String TIER = "tier";
|
||||||
|
private static final String WAND_LEVEL = "wand_level";
|
||||||
|
private static final String TOTAL_ZAPS = "total_zaps";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeInBundle(Bundle bundle) {
|
||||||
|
super.storeInBundle(bundle);
|
||||||
|
bundle.put(TIER, tier);
|
||||||
|
bundle.put(WAND_LEVEL, wandLevel);
|
||||||
|
bundle.put(TOTAL_ZAPS, totalZaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreFromBundle(Bundle bundle) {
|
||||||
|
super.restoreFromBundle(bundle);
|
||||||
|
tier = bundle.getInt(TIER);
|
||||||
|
wandLevel = bundle.getInt(WAND_LEVEL);
|
||||||
|
totalZaps = bundle.getInt(TOTAL_ZAPS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,6 +57,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.HighGrass;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.features.HighGrass;
|
||||||
|
@ -976,6 +977,22 @@ public abstract class Level implements Bundlable {
|
||||||
fieldOfView[p+i] = true;
|
fieldOfView[p+i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Mob ward : mobs){
|
||||||
|
if (ward instanceof WandOfWarding.Ward){
|
||||||
|
if (ward.fieldOfView == null || ward.fieldOfView.length != length()){
|
||||||
|
ward.fieldOfView = new boolean[length()];
|
||||||
|
Dungeon.level.updateFieldOfView( ward, ward.fieldOfView );
|
||||||
|
}
|
||||||
|
for (Mob m : mobs){
|
||||||
|
if (ward.fieldOfView[m.pos] && !fieldOfView[m.pos] &&
|
||||||
|
!Dungeon.hero.mindVisionEnemies.contains(m)){
|
||||||
|
Dungeon.hero.mindVisionEnemies.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BArray.or(fieldOfView, ward.fieldOfView, fieldOfView);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == Dungeon.hero) {
|
if (c == Dungeon.hero) {
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class SpinnerSprite extends MobSprite {
|
||||||
@Override
|
@Override
|
||||||
public void link(Char ch) {
|
public void link(Char ch) {
|
||||||
super.link(ch);
|
super.link(ch);
|
||||||
|
if (parent != null) parent.sendToBack(this);
|
||||||
renderShadow = false;
|
renderShadow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.sprites;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
|
||||||
|
import com.watabou.noosa.Game;
|
||||||
|
import com.watabou.noosa.tweeners.AlphaTweener;
|
||||||
|
|
||||||
|
public class WardSprite extends MobSprite {
|
||||||
|
|
||||||
|
private Animation tierIdles[] = new Animation[7];
|
||||||
|
|
||||||
|
public WardSprite(){
|
||||||
|
super();
|
||||||
|
|
||||||
|
texture(Assets.WARDS);
|
||||||
|
|
||||||
|
tierIdles[1] = new Animation( 1, true );
|
||||||
|
tierIdles[1].frames(texture.uvRect(0, 0, 9, 10));
|
||||||
|
|
||||||
|
tierIdles[2] = new Animation( 1, true );
|
||||||
|
tierIdles[2].frames(texture.uvRect(10, 0, 21, 12));
|
||||||
|
|
||||||
|
tierIdles[3] = new Animation( 1, true );
|
||||||
|
tierIdles[3].frames(texture.uvRect(22, 0, 37, 16));
|
||||||
|
|
||||||
|
tierIdles[4] = new Animation( 1, true );
|
||||||
|
tierIdles[4].frames(texture.uvRect(38, 0, 44, 13));
|
||||||
|
|
||||||
|
tierIdles[5] = new Animation( 1, true );
|
||||||
|
tierIdles[5].frames(texture.uvRect(45, 0, 51, 15));
|
||||||
|
|
||||||
|
tierIdles[6] = new Animation( 1, true );
|
||||||
|
tierIdles[6].frames(texture.uvRect(52, 0, 60, 15));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void zap( int pos ) {
|
||||||
|
idle();
|
||||||
|
flash();
|
||||||
|
emitter().burst(MagicMissile.WardParticle.UP, 2);
|
||||||
|
if (Actor.findChar(pos) != null){
|
||||||
|
parent.add(new Beam.DeathRay(center(), Actor.findChar(pos).sprite.center()));
|
||||||
|
} else {
|
||||||
|
parent.add(new Beam.DeathRay(center(), DungeonTilemap.raisedTileCenterToWorld(pos)));
|
||||||
|
}
|
||||||
|
((WandOfWarding.Ward)ch).onZapComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void die() {
|
||||||
|
super.die();
|
||||||
|
//cancels die animation and fades out immediately
|
||||||
|
play(idle, true);
|
||||||
|
emitter().burst(MagicMissile.WardParticle.UP, 10);
|
||||||
|
parent.add( new AlphaTweener( this, 0, 2f ) {
|
||||||
|
@Override
|
||||||
|
protected void onComplete() {
|
||||||
|
WardSprite.this.killAndErase();
|
||||||
|
parent.erase( this );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateTier(int tier){
|
||||||
|
|
||||||
|
idle = tierIdles[tier];
|
||||||
|
run = idle.clone();
|
||||||
|
//zap = idle.clone();
|
||||||
|
//attack = idle.clone();
|
||||||
|
die = idle.clone();
|
||||||
|
|
||||||
|
//always render first
|
||||||
|
if (parent != null) {
|
||||||
|
parent.sendToBack(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
idle();
|
||||||
|
|
||||||
|
if (tier <= 3){
|
||||||
|
shadowWidth = shadowHeight = 1f;
|
||||||
|
perspectiveRaise = (16 - height()) / 32f; //center of the cell
|
||||||
|
} else {
|
||||||
|
shadowWidth = 1.2f;
|
||||||
|
shadowHeight = 0.25f;
|
||||||
|
perspectiveRaise = 6 / 16f; //6 pixels
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch != null) {
|
||||||
|
place(ch.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float baseY;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void place(int cell) {
|
||||||
|
super.place(cell);
|
||||||
|
baseY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
super.update();
|
||||||
|
//if tier is greater than 3
|
||||||
|
if (perspectiveRaise >= 6 / 16f){
|
||||||
|
y = baseY + (float) Math.sin(Game.timeTotal);
|
||||||
|
shadowOffset = 0.25f - 0.8f*(float) Math.sin(Game.timeTotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user