v0.7.2: rebalanced 3 stones:
- clairvoyance adjusted, no longer disarms traps, now goes through walls - detect curse is now disarming. Disarms up to 9 traps in an AOE - aggression now forces targeting on whatever it is thrown at.
This commit is contained in:
parent
374a80ebec
commit
673582c5c4
|
@ -117,6 +117,11 @@ public class ShatteredPixelDungeon extends Game {
|
||||||
com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gloves.class,
|
com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gloves.class,
|
||||||
"com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Knuckles" );
|
"com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Knuckles" );
|
||||||
|
|
||||||
|
//v0.7.2
|
||||||
|
com.watabou.utils.Bundle.addAlias(
|
||||||
|
com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDisarming.class,
|
||||||
|
"com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDetectCurse" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -195,11 +195,15 @@ public abstract class Mob extends Char {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StoneOfAggression.Aggression aggro = buff( StoneOfAggression.Aggression.class );
|
//if we are an enemy, and have no target or current target isn't affected by aggression
|
||||||
if (aggro != null){
|
//then auto-prioritize a target that is affected by aggression, even another enemy
|
||||||
Char source = (Char)Actor.findById( aggro.object );
|
if (alignment == Alignment.ENEMY
|
||||||
if (source != null){
|
&& (enemy == null || enemy.buff(StoneOfAggression.Aggression.class) == null)) {
|
||||||
return source;
|
for (Char ch : Actor.chars()) {
|
||||||
|
if (ch != this && fieldOfView[ch.pos] &&
|
||||||
|
ch.buff(StoneOfAggression.Aggression.class) != null) {
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,6 +558,10 @@ public abstract class Mob extends Char {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTargeting( Char ch){
|
||||||
|
return enemy == ch;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void damage( int dmg, Object src ) {
|
public void damage( int dmg, Object src ) {
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfBlast;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfBlink;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfBlink;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfClairvoyance;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfClairvoyance;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDeepenedSleep;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDeepenedSleep;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDetectCurse;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDisarming;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFlock;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFlock;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition;
|
||||||
|
@ -287,7 +287,7 @@ public class Generator {
|
||||||
StoneOfBlink.class,
|
StoneOfBlink.class,
|
||||||
StoneOfClairvoyance.class,
|
StoneOfClairvoyance.class,
|
||||||
StoneOfDeepenedSleep.class,
|
StoneOfDeepenedSleep.class,
|
||||||
StoneOfDetectCurse.class,
|
StoneOfDisarming.class,
|
||||||
StoneOfFlock.class,
|
StoneOfFlock.class,
|
||||||
StoneOfShock.class
|
StoneOfShock.class
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,7 +40,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfBlast;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfBlink;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfBlink;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfClairvoyance;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfClairvoyance;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDeepenedSleep;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDeepenedSleep;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDetectCurse;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDisarming;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFlock;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFlock;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition;
|
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition;
|
||||||
|
@ -314,7 +314,7 @@ public abstract class Scroll extends Item {
|
||||||
stones.put(ScrollOfRecharging.class, StoneOfShock.class);
|
stones.put(ScrollOfRecharging.class, StoneOfShock.class);
|
||||||
amnts.put(ScrollOfRecharging.class, 2);
|
amnts.put(ScrollOfRecharging.class, 2);
|
||||||
|
|
||||||
stones.put(ScrollOfRemoveCurse.class, StoneOfDetectCurse.class);
|
stones.put(ScrollOfRemoveCurse.class, StoneOfDisarming.class);
|
||||||
amnts.put(ScrollOfRemoveCurse.class, 2);
|
amnts.put(ScrollOfRemoveCurse.class, 2);
|
||||||
|
|
||||||
stones.put(ScrollOfTeleportation.class, StoneOfBlink.class);
|
stones.put(ScrollOfTeleportation.class, StoneOfBlink.class);
|
||||||
|
|
|
@ -22,17 +22,19 @@
|
||||||
package com.shatteredpixel.shatteredpixeldungeon.items.stones;
|
package com.shatteredpixel.shatteredpixeldungeon.items.stones;
|
||||||
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
import com.watabou.noosa.audio.Sample;
|
import com.watabou.noosa.audio.Sample;
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
import com.watabou.utils.PathFinder;
|
|
||||||
|
|
||||||
public class StoneOfAggression extends Runestone {
|
public class StoneOfAggression extends Runestone {
|
||||||
|
|
||||||
|
@ -43,15 +45,21 @@ public class StoneOfAggression extends Runestone {
|
||||||
@Override
|
@Override
|
||||||
protected void activate(int cell) {
|
protected void activate(int cell) {
|
||||||
|
|
||||||
CellEmitter.center(cell).start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
|
Char ch = Actor.findChar( cell );
|
||||||
Sample.INSTANCE.play( Assets.SND_READ );
|
|
||||||
|
|
||||||
for (int i : PathFinder.NEIGHBOURS9){
|
if (ch != null) {
|
||||||
|
if (ch.alignment == Char.Alignment.ENEMY) {
|
||||||
Char ch = Actor.findChar( cell + i );
|
Buff.prolong(ch, Aggression.class, Aggression.DURATION / 5f);
|
||||||
|
} else {
|
||||||
if (ch != null && ch.alignment == Char.Alignment.ENEMY){
|
Buff.prolong(ch, Aggression.class, Aggression.DURATION);
|
||||||
Buff.prolong(ch, Aggression.class, Aggression.DURATION).object = curUser.id();
|
}
|
||||||
|
CellEmitter.center(cell).start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
|
||||||
|
Sample.INSTANCE.play( Assets.SND_READ );
|
||||||
|
} else {
|
||||||
|
//Item.onThrow
|
||||||
|
Heap heap = Dungeon.level.drop( this, cell );
|
||||||
|
if (!heap.isEmpty()) {
|
||||||
|
heap.sprite.drop( cell );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,11 +67,7 @@ public class StoneOfAggression extends Runestone {
|
||||||
|
|
||||||
public static class Aggression extends FlavourBuff {
|
public static class Aggression extends FlavourBuff {
|
||||||
|
|
||||||
public static final float DURATION = 10f;
|
public static final float DURATION = 20f;
|
||||||
|
|
||||||
public int object = 0;
|
|
||||||
|
|
||||||
private static final String OBJECT = "object";
|
|
||||||
|
|
||||||
{
|
{
|
||||||
type = buffType.NEGATIVE;
|
type = buffType.NEGATIVE;
|
||||||
|
@ -73,13 +77,25 @@ public class StoneOfAggression extends Runestone {
|
||||||
@Override
|
@Override
|
||||||
public void storeInBundle( Bundle bundle ) {
|
public void storeInBundle( Bundle bundle ) {
|
||||||
super.storeInBundle(bundle);
|
super.storeInBundle(bundle);
|
||||||
bundle.put(OBJECT, object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromBundle( Bundle bundle ) {
|
public void restoreFromBundle( Bundle bundle ) {
|
||||||
super.restoreFromBundle( bundle );
|
super.restoreFromBundle( bundle );
|
||||||
object = bundle.getInt( OBJECT );
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detach() {
|
||||||
|
//if our target is an enemy, reset the aggro of any enemies targeting it
|
||||||
|
if (target.alignment == Char.Alignment.ENEMY) {
|
||||||
|
for (Mob m : Dungeon.level.mobs) {
|
||||||
|
if (m.alignment == Char.Alignment.ENEMY && m.isTargeting(target)) {
|
||||||
|
m.aggro(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.detach();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -23,21 +23,13 @@ package com.shatteredpixel.shatteredpixeldungeon.items.stones;
|
||||||
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CheckedCell;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.CheckedCell;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMagicMapping;
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMagicMapping;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.ShadowCaster;
|
import com.shatteredpixel.shatteredpixeldungeon.mechanics.ShadowCaster;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
import com.watabou.noosa.audio.Sample;
|
import com.watabou.noosa.audio.Sample;
|
||||||
import com.watabou.utils.Point;
|
import com.watabou.utils.Point;
|
||||||
import com.watabou.utils.Random;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
public class StoneOfClairvoyance extends Runestone {
|
public class StoneOfClairvoyance extends Runestone {
|
||||||
|
|
||||||
|
@ -49,68 +41,40 @@ public class StoneOfClairvoyance extends Runestone {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate(final int cell) {
|
protected void activate(final int cell) {
|
||||||
boolean[] FOV = new boolean[Dungeon.level.length()];
|
|
||||||
Point c = Dungeon.level.cellToPoint(cell);
|
Point c = Dungeon.level.cellToPoint(cell);
|
||||||
ShadowCaster.castShadow(c.x, c.y, FOV, Dungeon.level.losBlocking, DIST);
|
|
||||||
|
|
||||||
int sX = Math.max(0, c.x - DIST);
|
int[] rounding = ShadowCaster.rounding[DIST];
|
||||||
int eX = Math.min(Dungeon.level.width()-1, c.x + DIST);
|
|
||||||
|
|
||||||
int sY = Math.max(0, c.y - DIST);
|
|
||||||
int eY = Math.min(Dungeon.level.height()-1, c.y + DIST);
|
|
||||||
|
|
||||||
ArrayList<Trap> disarmCandidates = new ArrayList<>();
|
|
||||||
|
|
||||||
|
int left, right;
|
||||||
|
int curr;
|
||||||
boolean noticed = false;
|
boolean noticed = false;
|
||||||
for (int y = sY; y <= eY; y++){
|
for (int y = Math.max(0, c.y - DIST); y <= Math.min(Dungeon.level.height()-1, c.y + DIST); y++) {
|
||||||
int curr = y*Dungeon.level.width() + sX;
|
if (rounding[Math.abs(c.y - y)] < Math.abs(c.y - y)) {
|
||||||
for ( int x = sX; x <= eX; x++){
|
left = c.x - rounding[Math.abs(c.y - y)];
|
||||||
|
} else {
|
||||||
if (FOV[curr]){
|
left = DIST;
|
||||||
curUser.sprite.parent.addToBack( new CheckedCell( curr ) );
|
while (rounding[left] < rounding[Math.abs(c.y - y)]){
|
||||||
Dungeon.level.mapped[curr] = true;
|
left--;
|
||||||
|
|
||||||
if (Dungeon.level.secret[curr]) {
|
|
||||||
Dungeon.level.discover(curr);
|
|
||||||
|
|
||||||
if (Dungeon.level.heroFOV[curr]) {
|
|
||||||
GameScene.discoverTile(curr, Dungeon.level.map[curr]);
|
|
||||||
ScrollOfMagicMapping.discover(curr);
|
|
||||||
noticed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Trap t = Dungeon.level.traps.get(curr);
|
|
||||||
if (t != null && t.active){
|
|
||||||
disarmCandidates.add(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
curr++;
|
left = c.x - left;
|
||||||
}
|
}
|
||||||
}
|
right = Math.min(Dungeon.level.width()-1, c.x + c.x - left);
|
||||||
|
left = Math.max(0, left);
|
||||||
|
for (curr = left + y * Dungeon.level.width(); curr <= right + y * Dungeon.level.width(); curr++){
|
||||||
|
|
||||||
Collections.sort(disarmCandidates, new Comparator<Trap>() {
|
curUser.sprite.parent.addToBack( new CheckedCell( curr ) );
|
||||||
@Override
|
Dungeon.level.mapped[curr] = true;
|
||||||
public int compare(Trap o1, Trap o2) {
|
|
||||||
float diff = Dungeon.level.trueDistance(cell, o1.pos) - Dungeon.level.trueDistance(cell, o2.pos);
|
if (Dungeon.level.secret[curr]) {
|
||||||
if (diff < 0){
|
Dungeon.level.discover(curr);
|
||||||
return -1;
|
|
||||||
} else if (diff == 0){
|
if (Dungeon.level.heroFOV[curr]) {
|
||||||
return Random.Int(2) == 0 ? -1 : 1;
|
GameScene.discoverTile(curr, Dungeon.level.map[curr]);
|
||||||
} else {
|
ScrollOfMagicMapping.discover(curr);
|
||||||
return 1;
|
noticed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//disarms at most two traps
|
|
||||||
if (disarmCandidates.size() > 0){
|
|
||||||
disarmCandidates.get(0).disarm();
|
|
||||||
CellEmitter.get(disarmCandidates.get(0).pos).burst(Speck.factory(Speck.STEAM), 6);
|
|
||||||
if (disarmCandidates.size() > 1){
|
|
||||||
disarmCandidates.get(1).disarm();
|
|
||||||
CellEmitter.get(disarmCandidates.get(1).pos).burst(Speck.factory(Speck.STEAM), 6);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +84,8 @@ public class StoneOfClairvoyance extends Runestone {
|
||||||
|
|
||||||
Sample.INSTANCE.play( Assets.SND_TELEPORT );
|
Sample.INSTANCE.play( Assets.SND_TELEPORT );
|
||||||
GameScene.updateFog();
|
GameScene.updateFog();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
* Pixel Dungeon
|
|
||||||
* Copyright (C) 2012-2015 Oleg Dolya
|
|
||||||
*
|
|
||||||
* Shattered Pixel Dungeon
|
|
||||||
* Copyright (C) 2014-2019 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.stones;
|
|
||||||
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
|
|
||||||
|
|
||||||
public class StoneOfDetectCurse extends InventoryStone {
|
|
||||||
|
|
||||||
{
|
|
||||||
mode = WndBag.Mode.CURSE_DETECTABLE;
|
|
||||||
image = ItemSpriteSheet.STONE_CURSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onItemSelected(Item item) {
|
|
||||||
|
|
||||||
item.cursedKnown = true;
|
|
||||||
useAnimation();
|
|
||||||
|
|
||||||
if (item.cursed){
|
|
||||||
GLog.w( Messages.get(this, "cursed") );
|
|
||||||
} else {
|
|
||||||
GLog.w( Messages.get(this, "not_cursed") );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean canDetectCurse(Item item){
|
|
||||||
return !item.isIdentified()
|
|
||||||
&& !item.cursedKnown
|
|
||||||
&& (item instanceof EquipableItem || item instanceof Wand);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Pixel Dungeon
|
||||||
|
* Copyright (C) 2012-2015 Oleg Dolya
|
||||||
|
*
|
||||||
|
* Shattered Pixel Dungeon
|
||||||
|
* Copyright (C) 2014-2019 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.stones;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.mechanics.ShadowCaster;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
|
import com.watabou.noosa.audio.Sample;
|
||||||
|
import com.watabou.utils.Point;
|
||||||
|
import com.watabou.utils.Random;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class StoneOfDisarming extends Runestone {
|
||||||
|
|
||||||
|
private static final int DIST = 8;
|
||||||
|
|
||||||
|
{
|
||||||
|
image = ItemSpriteSheet.STONE_DISARM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void activate(final int cell) {
|
||||||
|
boolean[] FOV = new boolean[Dungeon.level.length()];
|
||||||
|
Point c = Dungeon.level.cellToPoint(cell);
|
||||||
|
ShadowCaster.castShadow(c.x, c.y, FOV, Dungeon.level.losBlocking, DIST);
|
||||||
|
|
||||||
|
int sX = Math.max(0, c.x - DIST);
|
||||||
|
int eX = Math.min(Dungeon.level.width()-1, c.x + DIST);
|
||||||
|
|
||||||
|
int sY = Math.max(0, c.y - DIST);
|
||||||
|
int eY = Math.min(Dungeon.level.height()-1, c.y + DIST);
|
||||||
|
|
||||||
|
ArrayList<Trap> disarmCandidates = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int y = sY; y <= eY; y++){
|
||||||
|
int curr = y*Dungeon.level.width() + sX;
|
||||||
|
for ( int x = sX; x <= eX; x++){
|
||||||
|
|
||||||
|
if (FOV[curr]){
|
||||||
|
|
||||||
|
Trap t = Dungeon.level.traps.get(curr);
|
||||||
|
if (t != null && t.active){
|
||||||
|
disarmCandidates.add(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
curr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(disarmCandidates, new Comparator<Trap>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Trap o1, Trap o2) {
|
||||||
|
float diff = Dungeon.level.trueDistance(cell, o1.pos) - Dungeon.level.trueDistance(cell, o2.pos);
|
||||||
|
if (diff < 0){
|
||||||
|
return -1;
|
||||||
|
} else if (diff == 0){
|
||||||
|
return Random.Int(2) == 0 ? -1 : 1;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//disarms at most nine traps
|
||||||
|
while (disarmCandidates.size() > 9){
|
||||||
|
disarmCandidates.remove(9);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Trap t : disarmCandidates){
|
||||||
|
t.reveal();
|
||||||
|
t.disarm();
|
||||||
|
CellEmitter.get(t.pos).burst(Speck.factory(Speck.STEAM), 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sample.INSTANCE.play( Assets.SND_TELEPORT );
|
||||||
|
}
|
||||||
|
}
|
|
@ -477,7 +477,7 @@ public class ItemSpriteSheet {
|
||||||
public static final int STONE_BLINK = STONES+4;
|
public static final int STONE_BLINK = STONES+4;
|
||||||
public static final int STONE_CLAIRVOYANCE = STONES+5;
|
public static final int STONE_CLAIRVOYANCE = STONES+5;
|
||||||
public static final int STONE_SLEEP = STONES+6;
|
public static final int STONE_SLEEP = STONES+6;
|
||||||
public static final int STONE_CURSE = STONES+7;
|
public static final int STONE_DISARM = STONES+7;
|
||||||
public static final int STONE_ENCHANT = STONES+8;
|
public static final int STONE_ENCHANT = STONES+8;
|
||||||
public static final int STONE_FLOCK = STONES+9;
|
public static final int STONE_FLOCK = STONES+9;
|
||||||
public static final int STONE_INTUITION = STONES+10;
|
public static final int STONE_INTUITION = STONES+10;
|
||||||
|
|
|
@ -42,7 +42,6 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRemoveCurse;
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRemoveCurse;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation;
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTransmutation;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.spells.Recycle;
|
import com.shatteredpixel.shatteredpixeldungeon.items.spells.Recycle;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfDetectCurse;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
||||||
|
@ -87,7 +86,6 @@ public class WndBag extends WndTabbed {
|
||||||
POTION,
|
POTION,
|
||||||
SCROLL,
|
SCROLL,
|
||||||
UNIDED_POTION_OR_SCROLL,
|
UNIDED_POTION_OR_SCROLL,
|
||||||
CURSE_DETECTABLE,
|
|
||||||
EQUIPMENT,
|
EQUIPMENT,
|
||||||
TRANMSUTABLE,
|
TRANMSUTABLE,
|
||||||
ALCHEMY,
|
ALCHEMY,
|
||||||
|
@ -401,7 +399,6 @@ public class WndBag extends WndTabbed {
|
||||||
mode == Mode.POTION && (item instanceof Potion) ||
|
mode == Mode.POTION && (item instanceof Potion) ||
|
||||||
mode == Mode.SCROLL && (item instanceof Scroll) ||
|
mode == Mode.SCROLL && (item instanceof Scroll) ||
|
||||||
mode == Mode.UNIDED_POTION_OR_SCROLL && (!item.isIdentified() && (item instanceof Scroll || item instanceof Potion)) ||
|
mode == Mode.UNIDED_POTION_OR_SCROLL && (!item.isIdentified() && (item instanceof Scroll || item instanceof Potion)) ||
|
||||||
mode == Mode.CURSE_DETECTABLE && StoneOfDetectCurse.canDetectCurse(item) ||
|
|
||||||
mode == Mode.EQUIPMENT && (item instanceof EquipableItem) ||
|
mode == Mode.EQUIPMENT && (item instanceof EquipableItem) ||
|
||||||
mode == Mode.ALCHEMY && Recipe.usableInRecipe(item) ||
|
mode == Mode.ALCHEMY && Recipe.usableInRecipe(item) ||
|
||||||
mode == Mode.TRANMSUTABLE && ScrollOfTransmutation.canTransmute(item) ||
|
mode == Mode.TRANMSUTABLE && ScrollOfTransmutation.canTransmute(item) ||
|
||||||
|
|
|
@ -997,8 +997,8 @@ items.stones.inventorystone.ac_use=USE
|
||||||
items.stones.runestone$placeholder.name=runestone
|
items.stones.runestone$placeholder.name=runestone
|
||||||
|
|
||||||
items.stones.stoneofaggression.name=stone of aggression
|
items.stones.stoneofaggression.name=stone of aggression
|
||||||
items.stones.stoneofaggression.desc=When this stone is thrown near an enemy, it will afflict them with aggression magic.\n\nAn enemy under the influence of aggression will be forced to attack you instead of any allies, if any allies are nearby.
|
items.stones.stoneofaggression.desc=When this stone is thrown at an ally or enemy, all nearby enemies will be forced to attack that character for a short time.\n\nWhen used on enemies, the magic will only last for a few moments, but when used on yourself or allies it will last significantly longer.
|
||||||
items.stones.stoneofaggression$aggression.name=Aggression
|
items.stones.stoneofaggression$aggression.name=Targeted
|
||||||
|
|
||||||
items.stones.stoneofaugmentation.name=stone of augmentation
|
items.stones.stoneofaugmentation.name=stone of augmentation
|
||||||
items.stones.stoneofaugmentation.inv_title=Augment an item
|
items.stones.stoneofaugmentation.inv_title=Augment an item
|
||||||
|
@ -1021,16 +1021,13 @@ items.stones.stoneofblink.name=stone of blink
|
||||||
items.stones.stoneofblink.desc=This runestone will teleport the user to the location it is thrown to.
|
items.stones.stoneofblink.desc=This runestone will teleport the user to the location it is thrown to.
|
||||||
|
|
||||||
items.stones.stoneofclairvoyance.name=stone of clairvoyance
|
items.stones.stoneofclairvoyance.name=stone of clairvoyance
|
||||||
items.stones.stoneofclairvoyance.desc=This stone will instantly search all tiles which are visible from the location it is thrown to, and will disarm up to two traps which it finds.
|
items.stones.stoneofclairvoyance.desc=This stone will instantly reveal all tiles in a wide area around where it is thrown. Its effect will even reach through walls.
|
||||||
|
|
||||||
items.stones.stoneofdeepenedsleep.name=stone of deepened sleep
|
items.stones.stoneofdeepenedsleep.name=stone of deepened sleep
|
||||||
items.stones.stoneofdeepenedsleep.desc=When this stone is thrown near a sleeping enemy, it will magically deepen their sleep. Magically slept enemies will sleep forever until disturbed.
|
items.stones.stoneofdeepenedsleep.desc=When this stone is thrown near a sleeping enemy, it will magically deepen their sleep. Magically slept enemies will sleep forever until disturbed.
|
||||||
|
|
||||||
items.stones.stoneofdetectcurse.name=stone of detect curse
|
items.stones.stoneofdisarming.name=stone of disarming
|
||||||
items.stones.stoneofdetectcurse.inv_title=Detect an item
|
items.stones.stoneofdisarming.desc=This runestone holds magic that can disable malicious traps hidden throughout the dungeon. It will disarm up to 9 traps around the area it is thrown at.
|
||||||
items.stones.stoneofdetectcurse.cursed=You sense that the item is cursed!
|
|
||||||
items.stones.stoneofdetectcurse.not_cursed=There is no evil magic in that item.
|
|
||||||
items.stones.stoneofdetectcurse.desc=This runestone holds a weaker version of the magic found in scrolls of remove curse. While curses cannot be removed from an item, they will be detected.
|
|
||||||
|
|
||||||
items.stones.stoneofenchantment.name=stone of enchantment
|
items.stones.stoneofenchantment.name=stone of enchantment
|
||||||
items.stones.stoneofenchantment.inv_title=Enchant an item
|
items.stones.stoneofenchantment.inv_title=Enchant an item
|
||||||
|
|
Loading…
Reference in New Issue
Block a user