v1.1.0: reworked scroll of confusion into scroll of challenge

This commit is contained in:
Evan Debenham 2021-10-26 16:14:22 -04:00
parent 40993d3a90
commit 623c3776fd
10 changed files with 286 additions and 68 deletions

View File

@ -978,8 +978,10 @@ items.scrolls.exotic.scrollofsirenssong$enthralled.desc=This creature has been b
items.scrolls.exotic.scrollofantimagic.name=scroll of anti-magic items.scrolls.exotic.scrollofantimagic.name=scroll of anti-magic
items.scrolls.exotic.scrollofantimagic.desc=The incantation on this scroll will surround you with a magical aura that temporarily blocks all magical effects, harmful or helpful. items.scrolls.exotic.scrollofantimagic.desc=The incantation on this scroll will surround you with a magical aura that temporarily blocks all magical effects, harmful or helpful.
items.scrolls.exotic.scrollofconfusion.name=scroll of confusion items.scrolls.exotic.scrollofchallenge.name=scroll of challenge
items.scrolls.exotic.scrollofconfusion.desc=When read aloud, this scroll will unleash confusing magic on all targets in sight, blinding and disorienting them. items.scrolls.exotic.scrollofchallenge.desc=When read aloud, this scroll will unleash a great roar that draws enemies to the user while simultaneously creating a small arena around them.\n\nAs long as the reader stays in this arena they will take 33% less damage from all sources (this is applied before other forms of damage reduction), and they will not lose satiety.\n\nThe size of the arena will scale with the size of the area the reader is in. It will be particularly small in some boss areas.
items.scrolls.exotic.scrollofchallenge$challengearena.name=Challenge Arena
items.scrolls.exotic.scrollofchallenge$challengearena.desc=A scroll of challenge has created an arena around you, denoted by a billowing red fog.\n\nWhile standing in the fog, your hunger will not increase and you will take 33%% less damage from all sources. If you have any other sources of damage reduction (such as armor), they will apply after the 33%% reduction.\n\nTurns remaining: %d.
items.scrolls.exotic.scrollofdivination.name=scroll of divination items.scrolls.exotic.scrollofdivination.name=scroll of divination
items.scrolls.exotic.scrollofdivination.nothing_left=There is nothing left to identify! items.scrolls.exotic.scrollofdivination.nothing_left=There is nothing left to identify!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -52,6 +52,9 @@ public class ShatteredPixelDungeon extends Game {
com.watabou.utils.Bundle.addAlias( com.watabou.utils.Bundle.addAlias(
com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfSirensSong.class, com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfSirensSong.class,
"com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfAffection" ); "com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfAffection" );
com.watabou.utils.Bundle.addAlias(
com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfChallenge.class,
"com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfConfusion" );
//v1.0.0 //v1.0.0
com.watabou.utils.Bundle.addAlias( com.watabou.utils.Bundle.addAlias(

View File

@ -79,6 +79,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.PotionOfCle
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetribution; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetribution;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfChallenge;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast;
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfAggression; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfAggression;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast;
@ -358,6 +359,10 @@ public abstract class Char extends Actor {
dmg = endure.adjustDamageTaken(dmg); dmg = endure.adjustDamageTaken(dmg);
} }
if (enemy.buff(ScrollOfChallenge.ChallengeArena.class) != null){
dmg *= 0.67f;
}
int effectiveDamage = enemy.defenseProc( this, dmg ); int effectiveDamage = enemy.defenseProc( this, dmg );
effectiveDamage = Math.max( effectiveDamage - dr, 0 ); effectiveDamage = Math.max( effectiveDamage - dr, 0 );
@ -590,10 +595,16 @@ public abstract class Char extends Actor {
dmg *= 1.25f; dmg *= 1.25f;
} }
Endure.EndureTracker endure = buff(Endure.EndureTracker.class); Endure.EndureTracker endure = buff(Endure.EndureTracker.class);
//reduce damage here if it isn't coming from a chacter (if it is we already reduced it) if (!(src instanceof Char)){
if (endure != null && !(src instanceof Char)){ //reduce damage here if it isn't coming from a character (if it is we already reduced it)
if (endure != null){
dmg = endure.adjustDamageTaken(dmg); dmg = endure.adjustDamageTaken(dmg);
} }
//the same also applies to challenge scroll damage reduction
if (buff(ScrollOfChallenge.ChallengeArena.class) != null){
dmg *= 0.67f;
}
}
Class<?> srcClass = src.getClass(); Class<?> srcClass = src.getClass();
if (isImmune( srcClass )) { if (isImmune( srcClass )) {

View File

@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HornOfPlenty; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HornOfPlenty;
import com.shatteredpixel.shatteredpixeldungeon.items.journal.Guidebook; import com.shatteredpixel.shatteredpixeldungeon.items.journal.Guidebook;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfChallenge;
import com.shatteredpixel.shatteredpixeldungeon.journal.Document; import com.shatteredpixel.shatteredpixeldungeon.journal.Document;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
@ -64,7 +65,9 @@ public class Hunger extends Buff implements Hero.Doom {
@Override @Override
public boolean act() { public boolean act() {
if (Dungeon.level.locked || target.buff(WellFed.class) != null){ if (Dungeon.level.locked
|| target.buff(WellFed.class) != null
|| target.buff(ScrollOfChallenge.ChallengeArena.class) != null){
spend(STEP); spend(STEP);
return true; return true;
} }

View File

@ -0,0 +1,47 @@
package com.shatteredpixel.shatteredpixeldungeon.effects.particles;
import com.watabou.noosa.particles.Emitter;
import com.watabou.noosa.particles.PixelParticle;
import com.watabou.utils.Random;
public class ChallengeParticle extends PixelParticle.Shrinking {
public static final Emitter.Factory FACTORY = new Emitter.Factory() {
@Override
public void emit( Emitter emitter, int index, float x, float y ) {
((ChallengeParticle)emitter.recycle( ChallengeParticle.class )).reset( x, y );
}
@Override
public boolean lightMode() {
return false;
}
};
public ChallengeParticle() {
super();
lifespan = 0.6f;
color( 0xFF0000 );
}
public void reset( float x, float y){
revive();
this.x = x;
this.y = y;
left = lifespan;
size = 8;
speed.set( Random.Float( -8, +8 ), Random.Float( -16, -32 ) );
}
@Override
public void update() {
super.update();
am = 1 - left / lifespan;
}
}

View File

@ -60,8 +60,8 @@ public abstract class ExoticScroll extends Scroll {
regToExo.put(ScrollOfLullaby.class, ScrollOfSirensSong.class); regToExo.put(ScrollOfLullaby.class, ScrollOfSirensSong.class);
exoToReg.put(ScrollOfSirensSong.class, ScrollOfLullaby.class); exoToReg.put(ScrollOfSirensSong.class, ScrollOfLullaby.class);
regToExo.put(ScrollOfRage.class, ScrollOfConfusion.class); regToExo.put(ScrollOfRage.class, ScrollOfChallenge.class);
exoToReg.put(ScrollOfConfusion.class, ScrollOfRage.class); exoToReg.put(ScrollOfChallenge.class, ScrollOfRage.class);
regToExo.put(ScrollOfTerror.class, ScrollOfDread.class); regToExo.put(ScrollOfTerror.class, ScrollOfDread.class);
exoToReg.put(ScrollOfDread.class, ScrollOfTerror.class); exoToReg.put(ScrollOfDread.class, ScrollOfTerror.class);

View File

@ -0,0 +1,210 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2021 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.scrolls.exotic;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ChallengeParticle;
import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection.ConnectionRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.ShadowCaster;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.particles.Emitter;
import com.watabou.utils.Bundle;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Point;
import java.util.ArrayList;
import java.util.Arrays;
public class ScrollOfChallenge extends ExoticScroll {
{
icon = ItemSpriteSheet.Icons.SCROLL_CHALLENGE;
}
@Override
public void doRead() {
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
mob.beckon( curUser.pos );
}
Buff.affect(curUser, ChallengeArena.class).setup(curUser.pos);
identify();
curUser.sprite.centerEmitter().start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
Sample.INSTANCE.play( Assets.Sounds.CHALLENGE );
readAnimation();
}
public static class ChallengeArena extends Buff {
private ArrayList<Integer> arenaPositions = new ArrayList<>();
private ArrayList<Emitter> arenaEmitters = new ArrayList<>();
private static final float DURATION = 100;
int left = 0;
{
type = buffType.POSITIVE;
}
@Override
public int icon() {
return BuffIndicator.ARMOR;
}
@Override
public void tintIcon(Image icon) {
icon.hardlight(1f, 0f, 0f);
}
@Override
public float iconFadePercent() {
return Math.max(0, (DURATION - left) / DURATION);
}
@Override
public String toString() {
return Messages.get(this, "name");
}
@Override
public String desc() {
return Messages.get(this, "desc", left);
}
public void setup(int pos){
int dist;
if (Dungeon.depth == 5 || Dungeon.depth == 10 || Dungeon.depth == 20){
dist = 1; //smaller boss arenas
} else {
boolean[] visibleCells = new boolean[Dungeon.level.length()];
Point c = Dungeon.level.cellToPoint(pos);
ShadowCaster.castShadow(c.x, c.y, visibleCells, Dungeon.level.losBlocking, 8);
int count=0;
for (boolean b : visibleCells){
if (b) count++;
}
if (count < 30){
dist = 1;
} else if (count >= 100) {
dist = 3;
} else {
dist = 2;
}
}
PathFinder.buildDistanceMap( pos, BArray.or( Dungeon.level.passable, Dungeon.level.avoid, null ), dist );
for (int i = 0; i < PathFinder.distance.length; i++) {
if (PathFinder.distance[i] < Integer.MAX_VALUE && !arenaPositions.contains(i)) {
arenaPositions.add(i);
}
}
if (target != null) {
fx(false);
fx(true);
}
left = (int) DURATION;
}
@Override
public boolean act() {
if (!arenaPositions.contains(target.pos)){
detach();
}
left--;
BuffIndicator.refreshHero();
if (left <= 0){
detach();
}
spend(TICK);
return true;
}
@Override
public void fx(boolean on) {
if (on){
for (int i : arenaPositions){
Emitter e = CellEmitter.get(i);
e.pour(ChallengeParticle.FACTORY, 0.05f);
arenaEmitters.add(e);
}
} else {
for (Emitter e : arenaEmitters){
e.on = false;
}
arenaEmitters.clear();
}
}
private static final String ARENA_POSITIONS = "arena_positions";
private static final String LEFT = "left";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
int[] values = new int[arenaPositions.size()];
for (int i = 0; i < values.length; i ++)
values[i] = arenaPositions.get(i);
bundle.put(ARENA_POSITIONS, values);
bundle.put(LEFT, left);
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
int[] values = bundle.getIntArray( ARENA_POSITIONS );
for (int value : values) {
arenaPositions.add(value);
}
left = bundle.getInt(LEFT);
}
}
}

View File

@ -1,58 +0,0 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2021 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.scrolls.exotic;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.watabou.noosa.audio.Sample;
public class ScrollOfConfusion extends ExoticScroll {
{
icon = ItemSpriteSheet.Icons.SCROLL_CONFUSION;
}
@Override
public void doRead() {
for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
if (mob.alignment != Char.Alignment.ALLY && Dungeon.level.heroFOV[mob.pos]) {
Buff.prolong(mob, Vertigo.class, Vertigo.DURATION);
Buff.prolong(mob, Blindness.class, Blindness.DURATION);
}
}
identify();
curUser.sprite.centerEmitter().start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
Sample.INSTANCE.play( Assets.Sounds.READ );
readAnimation();
}
}

View File

@ -776,7 +776,7 @@ public class ItemSpriteSheet {
public static final int SCROLL_PASSAGE = EXOTIC_SCROLLS+5; public static final int SCROLL_PASSAGE = EXOTIC_SCROLLS+5;
public static final int SCROLL_SIREN = EXOTIC_SCROLLS+6; public static final int SCROLL_SIREN = EXOTIC_SCROLLS+6;
public static final int SCROLL_FORESIGHT= EXOTIC_SCROLLS+7; public static final int SCROLL_FORESIGHT= EXOTIC_SCROLLS+7;
public static final int SCROLL_CONFUSION= EXOTIC_SCROLLS+8; public static final int SCROLL_CHALLENGE= EXOTIC_SCROLLS+8;
public static final int SCROLL_PSIBLAST = EXOTIC_SCROLLS+9; public static final int SCROLL_PSIBLAST = EXOTIC_SCROLLS+9;
public static final int SCROLL_DREAD = EXOTIC_SCROLLS+10; public static final int SCROLL_DREAD = EXOTIC_SCROLLS+10;
public static final int SCROLL_POLYMORPH= EXOTIC_SCROLLS+11; public static final int SCROLL_POLYMORPH= EXOTIC_SCROLLS+11;
@ -789,7 +789,7 @@ public class ItemSpriteSheet {
assignIconRect( SCROLL_PASSAGE, 5, 7 ); assignIconRect( SCROLL_PASSAGE, 5, 7 );
assignIconRect( SCROLL_SIREN, 7, 6 ); assignIconRect( SCROLL_SIREN, 7, 6 );
assignIconRect( SCROLL_FORESIGHT, 7, 5 ); assignIconRect( SCROLL_FORESIGHT, 7, 5 );
assignIconRect( SCROLL_CONFUSION, 7, 7 ); assignIconRect( SCROLL_CHALLENGE, 7, 7 );
assignIconRect( SCROLL_PSIBLAST, 5, 6 ); assignIconRect( SCROLL_PSIBLAST, 5, 6 );
assignIconRect( SCROLL_DREAD, 5, 7 ); assignIconRect( SCROLL_DREAD, 5, 7 );
assignIconRect( SCROLL_POLYMORPH, 7, 6 ); assignIconRect( SCROLL_POLYMORPH, 7, 6 );