v1.1.0: overhauled search code and scroll of foresight

This commit is contained in:
Evan Debenham 2021-09-19 22:26:22 -04:00
parent a6bfe99b1f
commit dcbc12ae98
4 changed files with 72 additions and 40 deletions

View File

@ -159,7 +159,7 @@ actors.buffs.fireimbue.name=Imbued with Fire
actors.buffs.fireimbue.desc=You are imbued with the power of fire!\n\nAll physical attacks will have a chance to light enemies ablaze. Additionally, you are completely immune to the effects of fire.\n\nTurns of fire imbue remaining: %s.
actors.buffs.foresight.name=Foresight
actors.buffs.foresight.desc=Your senses are heightened, allowing you to immediately notice anything out of place.\n\nWhile under the effect of foresight your search radius is increased, and anything that enters your search radius is immediately discovered.\n\nTurns of foresight remaining: %s.
actors.buffs.foresight.desc=You are somehow able to see the layout of surrounding terrain with your mind.\n\nWhile under the effect of foresight all tiles in a wide radius are revealed to you, including any secret traps or doors.\n\nTurns of foresight remaining: %s.
actors.buffs.frost.name=Frozen
actors.buffs.frost.freezes=%s freezes!

View File

@ -988,7 +988,7 @@ items.scrolls.exotic.scrollofenchantment.cancel=cancel
items.scrolls.exotic.scrollofenchantment.desc=This scroll will infuse a weapon or armor with powerful magical energy. The reader even has some degree of control over which magic is imbued.
items.scrolls.exotic.scrollofforesight.name=scroll of foresight
items.scrolls.exotic.scrollofforesight.desc=When this scroll is read, the detail of nearby terrain will be constantly fed to the reader's mind in crystal clarity. For the duration of this effect, searching will not be necessary, as the reader will automatically detect everything within an enhanced search radius.
items.scrolls.exotic.scrollofforesight.desc=After reading this scroll, the detail of nearby terrain will be constantly fed to the reader's mind in crystal clarity. This effect lasts for a considerable amount of time, and will reveal all hidden doors or traps, making searching unnecessary.
items.scrolls.exotic.scrollofmysticalenergy.name=scroll of mystical energy
items.scrolls.exotic.scrollofmysticalenergy.desc=The raw magical power bound up in this parchment will, when released, charge a user's equipped artifacts over time.

View File

@ -21,12 +21,16 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.buffs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
public class Foresight extends FlavourBuff {
public static final float DURATION = 600f;
public static final float DURATION = 250f;
public static final int DISTANCE = 8;
{
type = buffType.POSITIVE;
@ -38,6 +42,20 @@ public class Foresight extends FlavourBuff {
return BuffIndicator.FORESIGHT;
}
@Override
public boolean attachTo(Char target) {
if (super.attachTo(target)){
//this way we get a nice VFX sweep on initial activation
if (target == Dungeon.hero){
Dungeon.level.mapped[target.pos] = false;
Dungeon.hero.search(false);
}
return true;
} else {
return false;
}
}
@Override
public float iconFadePercent() {
return Math.max(0, (DURATION - visualcooldown()) / DURATION);

View File

@ -140,6 +140,7 @@ import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.GameMath;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
import java.util.ArrayList;
@ -1872,47 +1873,57 @@ public class Hero extends Char {
if (hasTalent(Talent.WIDE_SEARCH)) distance++;
boolean foresight = buff(Foresight.class) != null;
if (foresight) distance++;
int cx = pos % Dungeon.level.width();
int cy = pos / Dungeon.level.width();
int ax = cx - distance;
if (ax < 0) {
ax = 0;
boolean foresightScan = foresight && !Dungeon.level.mapped[pos];
if (foresightScan){
Dungeon.level.mapped[pos] = true;
}
int bx = cx + distance;
if (bx >= Dungeon.level.width()) {
bx = Dungeon.level.width() - 1;
}
int ay = cy - distance;
if (ay < 0) {
ay = 0;
}
int by = cy + distance;
if (by >= Dungeon.level.height()) {
by = Dungeon.level.height() - 1;
if (foresight) {
distance = Foresight.DISTANCE;
circular = true;
}
Point c = Dungeon.level.cellToPoint(pos);
TalismanOfForesight.Foresight talisman = buff( TalismanOfForesight.Foresight.class );
boolean cursed = talisman != null && talisman.isCursed();
for (int y = ay; y <= by; y++) {
for (int x = ax, p = ax + y * Dungeon.level.width(); x <= bx; x++, p++) {
if (circular && Math.abs(x - cx)-1 > ShadowCaster.rounding[distance][distance - Math.abs(y - cy)]){
continue;
int[] rounding = ShadowCaster.rounding[distance];
int left, right;
int curr;
for (int y = Math.max(0, c.y - distance); y <= Math.min(Dungeon.level.height()-1, c.y + distance); y++) {
if (!circular){
left = c.x - distance;
} else if (rounding[Math.abs(c.y - y)] < Math.abs(c.y - y)) {
left = c.x - rounding[Math.abs(c.y - y)];
} else {
left = distance;
while (rounding[left] < rounding[Math.abs(c.y - y)]){
left--;
}
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++){
if (fieldOfView[p] && p != pos) {
if (intentional) {
GameScene.effectOverFog(new CheckedCell(p, pos));
if ((foresight || fieldOfView[curr]) && curr != pos) {
if ((foresight && (!Dungeon.level.mapped[curr] || foresightScan))){
GameScene.effectOverFog(new CheckedCell(curr, foresightScan ? pos : curr));
} else if (intentional) {
GameScene.effectOverFog(new CheckedCell(curr, pos));
}
if (foresight){
Dungeon.level.mapped[curr] = true;
}
if (Dungeon.level.secret[p]){
if (Dungeon.level.secret[curr]){
Trap trap = Dungeon.level.traps.get( p );
Trap trap = Dungeon.level.traps.get( curr );
float chance;
//searches aided by foresight always succeed, even if trap isn't searchable
@ -1932,7 +1943,7 @@ public class Hero extends Char {
chance = 0f;
//unintentional trap detection scales from 40% at floor 0 to 30% at floor 25
} else if (Dungeon.level.map[p] == Terrain.SECRET_TRAP) {
} else if (Dungeon.level.map[curr] == Terrain.SECRET_TRAP) {
chance = 0.4f - (Dungeon.depth / 250f);
//unintentional door detection scales from 20% at floor 0 to 0% at floor 20
@ -1942,15 +1953,15 @@ public class Hero extends Char {
if (Random.Float() < chance) {
int oldValue = Dungeon.level.map[p];
int oldValue = Dungeon.level.map[curr];
GameScene.discoverTile( p, oldValue );
GameScene.discoverTile( curr, oldValue );
Dungeon.level.discover( p );
Dungeon.level.discover( curr );
ScrollOfMagicMapping.discover( p );
ScrollOfMagicMapping.discover( curr );
smthFound = true;
if (fieldOfView[curr]) smthFound = true;
if (talisman != null){
if (oldValue == Terrain.SECRET_TRAP){
@ -1964,7 +1975,6 @@ public class Hero extends Char {
}
}
}
if (intentional) {
sprite.showStatus( CharSprite.DEFAULT, Messages.get(this, "search") );
@ -1986,6 +1996,10 @@ public class Hero extends Char {
Sample.INSTANCE.play( Assets.Sounds.SECRET );
interrupt();
}
if (foresight){
GameScene.updateFog(pos, Foresight.DISTANCE+1);
}
return smthFound;
}