v0.6.1: added empowered effects to scrolls

This commit is contained in:
Evan Debenham 2017-06-24 18:57:42 -04:00
parent b7f82b9488
commit 24eb803e3f
17 changed files with 300 additions and 31 deletions

View File

@ -36,7 +36,7 @@ public abstract class InventoryScroll extends Scroll {
protected WndBag.Mode mode = WndBag.Mode.ALL;
@Override
protected void doRead() {
public void doRead() {
if (!isKnown()) {
setKnown();

View File

@ -147,7 +147,10 @@ public abstract class Scroll extends Item {
}
}
abstract protected void doRead();
public abstract void doRead();
//currently only used in scrolls owned by the unstable spellbook
public abstract void empoweredRead();
protected void readAnimation() {
curUser.spend( TIME_TO_READ );

View File

@ -21,12 +21,17 @@
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.effects.Identification;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Random;
import java.util.ArrayList;
public class ScrollOfIdentify extends InventoryScroll {
@ -37,6 +42,24 @@ public class ScrollOfIdentify extends InventoryScroll {
bones = true;
}
@Override
public void empoweredRead() {
ArrayList<Item> unIDed = new ArrayList<>();
for( Item i : curUser.belongings){
if (!i.isIdentified()){
unIDed.add(i);
}
}
if (unIDed.size() > 1) {
Random.element(unIDed).identify();
Sample.INSTANCE.play( Assets.SND_TELEPORT );
}
doRead();
}
@Override
protected void onItemSelected( Item item ) {

View File

@ -40,7 +40,7 @@ public class ScrollOfLullaby extends Scroll {
}
@Override
protected void doRead() {
public void doRead() {
curUser.sprite.centerEmitter().start( Speck.factory( Speck.NOTE ), 0.3f, 5 );
Sample.INSTANCE.play( Assets.SND_LULLABY );
@ -62,6 +62,17 @@ public class ScrollOfLullaby extends Scroll {
readAnimation();
}
@Override
public void empoweredRead() {
doRead();
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (Level.fieldOfView[mob.pos]) {
Buff drowsy = mob.buff(Drowsy.class);
if (drowsy != null) drowsy.act();
}
}
}
@Override
public int price() {
return isKnown() ? 40 * quantity : super.price();

View File

@ -23,7 +23,10 @@ package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Awareness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.SpellSprite;
@ -41,7 +44,7 @@ public class ScrollOfMagicMapping extends Scroll {
}
@Override
protected void doRead() {
public void doRead() {
int length = Dungeon.level.length();
int[] map = Dungeon.level.map;
@ -86,6 +89,14 @@ public class ScrollOfMagicMapping extends Scroll {
readAnimation();
}
@Override
public void empoweredRead() {
doRead();
Buff.affect( curUser, MindVision.class, MindVision.DURATION );
Buff.affect( curUser, Awareness.class, Awareness.DURATION );
Dungeon.observe();
}
@Override
public int price() {
return isKnown() ? 40 * quantity : super.price();

View File

@ -56,6 +56,11 @@ public class ScrollOfMagicalInfusion extends InventoryScroll {
Enchanting.show(curUser, item);
}
@Override
public void empoweredRead() {
//does nothing for now, this should never happen.
}
@Override
public int price() {
return isKnown() ? 100 * quantity : super.price();

View File

@ -23,11 +23,15 @@ package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
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.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.MirrorImage;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
@ -42,31 +46,10 @@ public class ScrollOfMirrorImage extends Scroll {
private static final int NIMAGES = 3;
@Override
protected void doRead() {
public void doRead() {
int spawnedImages = spawnImages(curUser, NIMAGES);
ArrayList<Integer> respawnPoints = new ArrayList<Integer>();
for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) {
int p = curUser.pos + PathFinder.NEIGHBOURS8[i];
if (Actor.findChar( p ) == null && (Level.passable[p] || Level.avoid[p])) {
respawnPoints.add( p );
}
}
int nImages = NIMAGES;
while (nImages > 0 && respawnPoints.size() > 0) {
int index = Random.index( respawnPoints );
MirrorImage mob = new MirrorImage();
mob.duplicate( curUser );
GameScene.add( mob );
ScrollOfTeleportation.appear( mob, respawnPoints.get( index ) );
respawnPoints.remove( index );
nImages--;
}
if (nImages < NIMAGES) {
if (spawnedImages > 0) {
setKnown();
}
@ -76,6 +59,112 @@ public class ScrollOfMirrorImage extends Scroll {
readAnimation();
}
@Override
public void empoweredRead() {
//spawns 2 images right away, delays 4 of them, 6 total.
new DelayedImageSpawner(6 - spawnImages(curUser, 2), 2, 3).attachTo(curUser);
setKnown();
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
readAnimation();
}
//returns the number of images spawned
public static int spawnImages( Hero hero, int nImages ){
ArrayList<Integer> respawnPoints = new ArrayList<Integer>();
for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) {
int p = hero.pos + PathFinder.NEIGHBOURS8[i];
if (Actor.findChar( p ) == null && (Level.passable[p] || Level.avoid[p])) {
respawnPoints.add( p );
}
}
int spawned = 0;
while (nImages > 0 && respawnPoints.size() > 0) {
int index = Random.index( respawnPoints );
MirrorImage mob = new MirrorImage();
mob.duplicate( curUser );
GameScene.add( mob );
ScrollOfTeleportation.appear( mob, respawnPoints.get( index ) );
respawnPoints.remove( index );
nImages--;
spawned++;
}
return spawned;
}
public static class DelayedImageSpawner extends Buff{
public DelayedImageSpawner(){
this(NIMAGES, NIMAGES, 1);
}
public DelayedImageSpawner( int total, int perRound, float delay){
super();
totImages = total;
imPerRound = perRound;
this.delay = delay;
}
private int totImages;
private int imPerRound;
private float delay;
@Override
public boolean attachTo(Char target) {
if (super.attachTo(target)){
spend(delay);
return true;
} else {
return false;
}
}
@Override
public boolean act() {
int spawned = spawnImages((Hero)target, Math.min(totImages, imPerRound));
totImages -= spawned;
if (totImages <0){
detach();
} else {
spend( delay );
}
return true;
}
private static final String TOTAL = "images";
private static final String PER_ROUND = "per_round";
private static final String DELAY = "delay";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put( TOTAL, totImages );
bundle.put( PER_ROUND, imPerRound );
bundle.put( DELAY, delay );
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
totImages = bundle.getInt( TOTAL );
imPerRound = bundle.getInt( PER_ROUND );
delay = bundle.getFloat( DELAY );
}
}
@Override
public int price() {
return isKnown() ? 30 * quantity : super.price();

View File

@ -44,7 +44,7 @@ public class ScrollOfPsionicBlast extends Scroll {
}
@Override
protected void doRead() {
public void doRead() {
GameScene.flash( 0xFFFFFF );
@ -64,7 +64,7 @@ public class ScrollOfPsionicBlast extends Scroll {
setKnown();
curUser.spendAndNext( TIME_TO_READ ); //no animation here, the flash interrupts it anyway.
readAnimation();
if (!curUser.isAlive()) {
Dungeon.fail( getClass() );
@ -72,6 +72,24 @@ public class ScrollOfPsionicBlast extends Scroll {
}
}
@Override
public void empoweredRead() {
GameScene.flash( 0xFFFFFF );
Sample.INSTANCE.play( Assets.SND_BLAST );
Invisibility.dispel();
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (Level.fieldOfView[mob.pos]) {
mob.damage(mob.HT, this );
}
}
setKnown();
readAnimation();
}
@Override
public int price() {
return isKnown() ? 50 * quantity : super.price();

View File

@ -42,7 +42,7 @@ public class ScrollOfRage extends Scroll {
}
@Override
protected void doRead() {
public void doRead() {
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
mob.beckon( curUser.pos );
@ -71,6 +71,23 @@ public class ScrollOfRage extends Scroll {
readAnimation();
}
@Override
public void empoweredRead() {
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (Level.fieldOfView[mob.pos]) {
Buff.prolong(mob, Amok.class, 5f);
}
}
setKnown();
curUser.sprite.centerEmitter().start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
readAnimation();
}
@Override
public int price() {
return isKnown() ? 30 * quantity : super.price();

View File

@ -41,7 +41,7 @@ public class ScrollOfRecharging extends Scroll {
}
@Override
protected void doRead() {
public void doRead() {
Buff.affect(curUser, Recharging.class, BUFF_DURATION);
charge(curUser);
@ -56,6 +56,12 @@ public class ScrollOfRecharging extends Scroll {
readAnimation();
}
@Override
public void empoweredRead() {
doRead();
Buff.append(curUser, Recharging.class, BUFF_DURATION/3f);
}
public static void charge( Hero hero ) {
hero.sprite.centerEmitter().burst( EnergyParticle.FACTORY, 15 );
}

View File

@ -21,6 +21,8 @@
package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
@ -32,6 +34,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.watabou.noosa.audio.Sample;
public class ScrollOfRemoveCurse extends InventoryScroll {
@ -40,6 +43,18 @@ public class ScrollOfRemoveCurse extends InventoryScroll {
mode = WndBag.Mode.UNIDED_OR_CURSED;
}
@Override
public void empoweredRead() {
for (Item item : curUser.belongings){
if (item.cursed){
item.cursedKnown = true;
}
}
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
doRead();
}
@Override
protected void onItemSelected(Item item) {
new Flare( 6, 32 ).show( curUser.sprite, 2f ) ;

View File

@ -23,15 +23,21 @@ package com.shatteredpixel.shatteredpixeldungeon.items.scrolls;
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.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.tweeners.AlphaTweener;
import com.watabou.utils.PathFinder;
public class ScrollOfTeleportation extends Scroll {
@ -40,7 +46,7 @@ public class ScrollOfTeleportation extends Scroll {
}
@Override
protected void doRead() {
public void doRead() {
Sample.INSTANCE.play( Assets.SND_READ );
Invisibility.dispel();
@ -51,6 +57,48 @@ public class ScrollOfTeleportation extends Scroll {
readAnimation();
}
@Override
public void empoweredRead() {
if (Dungeon.bossLevel()){
GLog.w( Messages.get(this, "no_tele") );
return;
}
GameScene.selectCell(new CellSelector.Listener() {
@Override
public void onSelect(Integer target) {
if (target != null) {
//time isn't spent
((HeroSprite)curUser.sprite).read();
teleportToLocation(curUser, target);
}
}
@Override
public String prompt() {
return Messages.get(ScrollOfTeleportation.class, "prompt");
}
});
}
public static void teleportToLocation(Hero hero, int pos){
PathFinder.buildDistanceMap(pos, BArray.or(Level.passable, Level.avoid, null));
if (PathFinder.distance[hero.pos] == Integer.MAX_VALUE
|| (!Level.passable[pos] && !Level.avoid[pos])
|| Actor.findChar(pos) != null){
GLog.w( Messages.get(ScrollOfTeleportation.class, "cant_reach") );
return;
}
appear( hero, pos );
Dungeon.level.press( pos, hero );
Dungeon.observe();
GameScene.updateFog();
GLog.i( Messages.get(ScrollOfTeleportation.class, "tele") );
}
public static void teleportHero(Hero hero ) {
int count = 10;

View File

@ -25,6 +25,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
@ -40,7 +41,7 @@ public class ScrollOfTerror extends Scroll {
}
@Override
protected void doRead() {
public void doRead() {
new Flare( 5, 32 ).color( 0xFF0000, true ).show( curUser.sprite, 2f );
Sample.INSTANCE.play( Assets.SND_READ );
@ -74,6 +75,20 @@ public class ScrollOfTerror extends Scroll {
readAnimation();
}
@Override
public void empoweredRead() {
doRead();
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (Level.fieldOfView[mob.pos]) {
Terror t = mob.buff(Terror.class);
if (t != null){
Buff.prolong(mob, Terror.class, Terror.DURATION*1.5f);
Buff.affect(mob, Paralysis.class, Terror.DURATION*.5f);
}
}
}
}
@Override
public int price() {
return isKnown() ? 30 * quantity : super.price();

View File

@ -115,6 +115,11 @@ public class ScrollOfUpgrade extends InventoryScroll {
hero.sprite.emitter().start( ShadowParticle.UP, 0.05f, 10 );
}
@Override
public void empoweredRead() {
//does nothing for now, this should never happen.
}
@Override
public int price() {
return isKnown() ? 50 * quantity : super.price();

View File

@ -434,11 +434,12 @@ public abstract class Wand extends Item {
if (lock == null || lock.regenOn())
partialCharge += 1f/turnsToCharge;
Recharging bonus = target.buff(Recharging.class);
for (Recharging bonus : target.buffs(Recharging.class)){
if (bonus != null && bonus.remainder() > 0f) {
partialCharge += CHARGE_BUFF_BONUS * bonus.remainder();
}
}
}
public void gainCharge(float charge){
partialCharge += charge;

View File

@ -612,6 +612,8 @@ items.scrolls.scrollofremovecurse.desc=The incantation on this scroll will insta
items.scrolls.scrollofteleportation.name=scroll of teleportation
items.scrolls.scrollofteleportation.tele=In a blink of an eye you were teleported to another location of the level.
items.scrolls.scrollofteleportation.no_tele=Strong magic aura of this place prevents you from teleporting!
items.scrolls.scrollofteleportation.cant_reach=You can't teleport there
items.scrolls.scrollofteleportation.prompt=Choose a location to teleport
items.scrolls.scrollofteleportation.desc=The spell on this parchment instantly transports the reader to a random location on the dungeon level. It can be used to escape a dangerous situation, but the unlucky reader might find themselves in an even more dangerous place.
items.scrolls.scrollofterror.name=scroll of terror