v0.8.2: improvements to cone AOEs and fireblast:
- items which use cones can now trickshot - fireblast now bursts open doors instead of colliding with them
This commit is contained in:
parent
2895c212f7
commit
16822095df
|
@ -144,7 +144,7 @@ public class TalismanOfForesight extends Artifact {
|
||||||
|
|
||||||
//starts at 200 degrees, loses 8% per tile of distance
|
//starts at 200 degrees, loses 8% per tile of distance
|
||||||
float angle = Math.round(200*(float)Math.pow(0.92, dist));
|
float angle = Math.round(200*(float)Math.pow(0.92, dist));
|
||||||
ConeAOE cone = new ConeAOE(curUser.pos, target, angle);
|
ConeAOE cone = new ConeAOE(new Ballistica(curUser.pos, target, Ballistica.STOP_TARGET), angle);
|
||||||
|
|
||||||
int earnedExp = 0;
|
int earnedExp = 0;
|
||||||
boolean noticed = false;
|
boolean noticed = false;
|
||||||
|
|
|
@ -40,6 +40,9 @@ 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.Callback;
|
import com.watabou.utils.Callback;
|
||||||
|
import com.watabou.utils.PathFinder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class PotionOfDragonsBreath extends ExoticPotion {
|
public class PotionOfDragonsBreath extends ExoticPotion {
|
||||||
|
|
||||||
|
@ -77,12 +80,12 @@ public class PotionOfDragonsBreath extends ExoticPotion {
|
||||||
curUser.sprite.zap(cell);
|
curUser.sprite.zap(cell);
|
||||||
Sample.INSTANCE.play( Assets.Sounds.BURNING );
|
Sample.INSTANCE.play( Assets.Sounds.BURNING );
|
||||||
|
|
||||||
final Ballistica bolt = new Ballistica(curUser.pos, cell, Ballistica.STOP_TERRAIN);
|
final Ballistica bolt = new Ballistica(curUser.pos, cell, Ballistica.STOP_TERRAIN | Ballistica.OPEN_DOORS);
|
||||||
|
|
||||||
int maxDist = 6;
|
int maxDist = 6;
|
||||||
int dist = Math.min(bolt.dist, maxDist);
|
int dist = Math.min(bolt.dist, maxDist);
|
||||||
|
|
||||||
final ConeAOE cone = new ConeAOE(curUser.pos, bolt.path.get(dist), 6, 60, Ballistica.STOP_TERRAIN | Ballistica.STOP_TARGET );
|
final ConeAOE cone = new ConeAOE(bolt, 6, 60, Ballistica.STOP_TERRAIN | Ballistica.STOP_TARGET | Ballistica.OPEN_DOORS );
|
||||||
|
|
||||||
//cast to cells at the tip, rather than all cells, better performance.
|
//cast to cells at the tip, rather than all cells, better performance.
|
||||||
for (Ballistica ray : cone.rays){
|
for (Ballistica ray : cone.rays){
|
||||||
|
@ -101,6 +104,7 @@ public class PotionOfDragonsBreath extends ExoticPotion {
|
||||||
new Callback() {
|
new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void call() {
|
public void call() {
|
||||||
|
ArrayList<Integer> adjacentCells = new ArrayList<>();
|
||||||
for (int cell : cone.cells){
|
for (int cell : cone.cells){
|
||||||
//ignore caster cell
|
//ignore caster cell
|
||||||
if (cell == bolt.sourcePos){
|
if (cell == bolt.sourcePos){
|
||||||
|
@ -108,7 +112,9 @@ public class PotionOfDragonsBreath extends ExoticPotion {
|
||||||
}
|
}
|
||||||
|
|
||||||
//only ignite cells directly near caster if they are flammable
|
//only ignite cells directly near caster if they are flammable
|
||||||
if (!Dungeon.level.adjacent(bolt.sourcePos, cell) || Dungeon.level.flamable[cell]){
|
if (Dungeon.level.adjacent(bolt.sourcePos, cell) && !Dungeon.level.flamable[cell]){
|
||||||
|
adjacentCells.add(cell);
|
||||||
|
} else {
|
||||||
GameScene.add( Blob.seed( cell, 5, Fire.class ) );
|
GameScene.add( Blob.seed( cell, 5, Fire.class ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +125,19 @@ public class PotionOfDragonsBreath extends ExoticPotion {
|
||||||
Buff.affect(ch, Cripple.class, 5f);
|
Buff.affect(ch, Cripple.class, 5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ignite cells that share a side with an adjacent cell, are flammable, and are further from the source pos
|
||||||
|
//This prevents short-range casts not igniting barricades or bookshelves
|
||||||
|
for (int cell : adjacentCells){
|
||||||
|
for (int i : PathFinder.NEIGHBOURS4){
|
||||||
|
if (Dungeon.level.trueDistance(cell+i, bolt.sourcePos) > Dungeon.level.trueDistance(cell, bolt.sourcePos)
|
||||||
|
&& Dungeon.level.flamable[cell+i]
|
||||||
|
&& Fire.volumeAt(cell+i, Fire.class) == 0){
|
||||||
|
GameScene.add( Blob.seed( cell+i, 5, Fire.class ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
curUser.next();
|
curUser.next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,6 +41,7 @@ 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.Callback;
|
import com.watabou.utils.Callback;
|
||||||
|
import com.watabou.utils.PathFinder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ public class WandOfFireblast extends DamageWand {
|
||||||
{
|
{
|
||||||
image = ItemSpriteSheet.WAND_FIREBOLT;
|
image = ItemSpriteSheet.WAND_FIREBOLT;
|
||||||
|
|
||||||
collisionProperties = Ballistica.STOP_TERRAIN;
|
collisionProperties = Ballistica.STOP_TERRAIN | Ballistica.OPEN_DOORS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//1x/2x/3x damage
|
//1x/2x/3x damage
|
||||||
|
@ -68,6 +69,7 @@ public class WandOfFireblast extends DamageWand {
|
||||||
protected void onZap( Ballistica bolt ) {
|
protected void onZap( Ballistica bolt ) {
|
||||||
|
|
||||||
ArrayList<Char> affectedChars = new ArrayList<>();
|
ArrayList<Char> affectedChars = new ArrayList<>();
|
||||||
|
ArrayList<Integer> adjacentCells = new ArrayList<>();
|
||||||
for( int cell : cone.cells ){
|
for( int cell : cone.cells ){
|
||||||
|
|
||||||
//ignore caster cell
|
//ignore caster cell
|
||||||
|
@ -76,7 +78,9 @@ public class WandOfFireblast extends DamageWand {
|
||||||
}
|
}
|
||||||
|
|
||||||
//only ignite cells directly near caster if they are flammable
|
//only ignite cells directly near caster if they are flammable
|
||||||
if (!Dungeon.level.adjacent(bolt.sourcePos, cell) || Dungeon.level.flamable[cell]){
|
if (Dungeon.level.adjacent(bolt.sourcePos, cell) && !Dungeon.level.flamable[cell]){
|
||||||
|
adjacentCells.add(cell);
|
||||||
|
} else {
|
||||||
GameScene.add( Blob.seed( cell, 1+chargesPerCast(), Fire.class ) );
|
GameScene.add( Blob.seed( cell, 1+chargesPerCast(), Fire.class ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +90,18 @@ public class WandOfFireblast extends DamageWand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ignite cells that share a side with an adjacent cell, are flammable, and are further from the source pos
|
||||||
|
//This prevents short-range casts not igniting barricades or bookshelves
|
||||||
|
for (int cell : adjacentCells){
|
||||||
|
for (int i : PathFinder.NEIGHBOURS4){
|
||||||
|
if (Dungeon.level.trueDistance(cell+i, bolt.sourcePos) > Dungeon.level.trueDistance(cell, bolt.sourcePos)
|
||||||
|
&& Dungeon.level.flamable[cell+i]
|
||||||
|
&& Fire.volumeAt(cell+i, Fire.class) == 0){
|
||||||
|
GameScene.add( Blob.seed( cell+i, 1+chargesPerCast(), Fire.class ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( Char ch : affectedChars ){
|
for ( Char ch : affectedChars ){
|
||||||
processSoulMark(ch, chargesPerCast());
|
processSoulMark(ch, chargesPerCast());
|
||||||
ch.damage(damageRoll(), this);
|
ch.damage(damageRoll(), this);
|
||||||
|
@ -119,7 +135,7 @@ public class WandOfFireblast extends DamageWand {
|
||||||
int maxDist = 2 + 2*chargesPerCast();
|
int maxDist = 2 + 2*chargesPerCast();
|
||||||
int dist = Math.min(bolt.dist, maxDist);
|
int dist = Math.min(bolt.dist, maxDist);
|
||||||
|
|
||||||
cone = new ConeAOE( bolt.sourcePos, bolt.path.get(dist),
|
cone = new ConeAOE( bolt,
|
||||||
maxDist,
|
maxDist,
|
||||||
30 + 20*chargesPerCast(),
|
30 + 20*chargesPerCast(),
|
||||||
collisionProperties | Ballistica.STOP_TARGET);
|
collisionProperties | Ballistica.STOP_TARGET);
|
||||||
|
|
|
@ -203,7 +203,7 @@ public class WandOfRegrowth extends Wand {
|
||||||
int maxDist = 2 + 2*chargesPerCast();
|
int maxDist = 2 + 2*chargesPerCast();
|
||||||
int dist = Math.min(bolt.dist, maxDist);
|
int dist = Math.min(bolt.dist, maxDist);
|
||||||
|
|
||||||
cone = new ConeAOE( bolt.sourcePos, bolt.path.get(dist),
|
cone = new ConeAOE( bolt,
|
||||||
maxDist,
|
maxDist,
|
||||||
20 + 10*chargesPerCast(),
|
20 + 10*chargesPerCast(),
|
||||||
collisionProperties | Ballistica.STOP_TARGET);
|
collisionProperties | Ballistica.STOP_TARGET);
|
||||||
|
|
|
@ -24,6 +24,9 @@ package com.shatteredpixel.shatteredpixeldungeon.mechanics;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -38,9 +41,10 @@ public class Ballistica {
|
||||||
public Integer dist = 0;
|
public Integer dist = 0;
|
||||||
|
|
||||||
//parameters to specify the colliding cell
|
//parameters to specify the colliding cell
|
||||||
public static final int STOP_TARGET = 1; //ballistica will stop at the target cell
|
public static final int STOP_TARGET = 1; //ballistica will stop at the target cell
|
||||||
public static final int STOP_CHARS = 2; //ballistica will stop on first char hit
|
public static final int STOP_CHARS = 2; //ballistica will stop on first char hit
|
||||||
public static final int STOP_TERRAIN = 4; //ballistica will stop on terrain(LOS blocking, impassable, etc.)
|
public static final int STOP_TERRAIN = 4; //ballistica will stop on solid terrain
|
||||||
|
public static final int OPEN_DOORS = 8; //ballistica will open doors instead of colliding
|
||||||
|
|
||||||
public static final int PROJECTILE = STOP_TARGET | STOP_CHARS | STOP_TERRAIN;
|
public static final int PROJECTILE = STOP_TARGET | STOP_CHARS | STOP_TERRAIN;
|
||||||
|
|
||||||
|
@ -51,7 +55,12 @@ public class Ballistica {
|
||||||
|
|
||||||
public Ballistica( int from, int to, int params ){
|
public Ballistica( int from, int to, int params ){
|
||||||
sourcePos = from;
|
sourcePos = from;
|
||||||
build(from, to, (params & STOP_TARGET) > 0, (params & STOP_CHARS) > 0, (params & STOP_TERRAIN) > 0);
|
build(from, to,
|
||||||
|
(params & STOP_TARGET) > 0,
|
||||||
|
(params & STOP_CHARS) > 0,
|
||||||
|
(params & STOP_TERRAIN) > 0,
|
||||||
|
(params & OPEN_DOORS) > 0);
|
||||||
|
|
||||||
if (collisionPos != null) {
|
if (collisionPos != null) {
|
||||||
dist = path.indexOf(collisionPos);
|
dist = path.indexOf(collisionPos);
|
||||||
} else if (!path.isEmpty()) {
|
} else if (!path.isEmpty()) {
|
||||||
|
@ -63,7 +72,7 @@ public class Ballistica {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void build( int from, int to, boolean stopTarget, boolean stopChars, boolean stopTerrain ) {
|
private void build( int from, int to, boolean stopTarget, boolean stopChars, boolean stopTerrain, boolean openDoors ) {
|
||||||
int w = Dungeon.level.width();
|
int w = Dungeon.level.width();
|
||||||
|
|
||||||
int x0 = from % w;
|
int x0 = from % w;
|
||||||
|
@ -114,6 +123,11 @@ public class Ballistica {
|
||||||
|
|
||||||
path.add(cell);
|
path.add(cell);
|
||||||
|
|
||||||
|
if (openDoors && collisionPos == null && Dungeon.level.map[cell] == Terrain.DOOR){
|
||||||
|
Level.set(cell, Terrain.OPEN_DOOR);
|
||||||
|
GameScene.updateMap(cell);
|
||||||
|
}
|
||||||
|
|
||||||
if ((stopTerrain && cell != sourcePos && Dungeon.level.solid[cell])
|
if ((stopTerrain && cell != sourcePos && Dungeon.level.solid[cell])
|
||||||
|| (cell != sourcePos && stopChars && Actor.findChar( cell ) != null)
|
|| (cell != sourcePos && stopChars && Actor.findChar( cell ) != null)
|
||||||
|| (cell == to && stopTarget)){
|
|| (cell == to && stopTarget)){
|
||||||
|
|
|
@ -33,21 +33,26 @@ import java.util.LinkedHashSet;
|
||||||
//a cone made of up several ballisticas scanning in an arc
|
//a cone made of up several ballisticas scanning in an arc
|
||||||
public class ConeAOE {
|
public class ConeAOE {
|
||||||
|
|
||||||
|
public Ballistica coreRay;
|
||||||
|
|
||||||
public ArrayList<Ballistica> rays = new ArrayList<>();
|
public ArrayList<Ballistica> rays = new ArrayList<>();
|
||||||
public HashSet<Integer> cells = new HashSet<>();
|
public HashSet<Integer> cells = new HashSet<>();
|
||||||
|
|
||||||
public ConeAOE( int from, int to, float degrees ){
|
public ConeAOE( Ballistica core, float degrees ){
|
||||||
this(from, to, Float.POSITIVE_INFINITY, degrees, Ballistica.STOP_TARGET);
|
this( core, Float.POSITIVE_INFINITY, degrees, Ballistica.STOP_TARGET/* TODO */);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConeAOE( int from, int to, float maxDist, float degrees, int ballisticaParams ){
|
public ConeAOE( Ballistica core, float maxDist, float degrees, int ballisticaParams ){
|
||||||
|
|
||||||
|
coreRay = core;
|
||||||
|
|
||||||
//we want to use true coordinates for our trig functions, not game cells
|
//we want to use true coordinates for our trig functions, not game cells
|
||||||
// so get the center of from and to as points
|
// so get the center of from and to as points
|
||||||
PointF fromP = new PointF(Dungeon.level.cellToPoint(from));
|
PointF fromP = new PointF(Dungeon.level.cellToPoint(core.sourcePos));
|
||||||
fromP.x += 0.5f;
|
fromP.x += 0.5f;
|
||||||
fromP.y += 0.5f;
|
fromP.y += 0.5f;
|
||||||
PointF toP = new PointF(Dungeon.level.cellToPoint(to));
|
|
||||||
|
PointF toP = new PointF(Dungeon.level.cellToPoint(core.collisionPos));
|
||||||
toP.x += 0.5f;
|
toP.x += 0.5f;
|
||||||
toP.y += 0.5f;
|
toP.y += 0.5f;
|
||||||
|
|
||||||
|
@ -94,11 +99,18 @@ public class ConeAOE {
|
||||||
|
|
||||||
//cast a ray to each found cell, these make up the cone
|
//cast a ray to each found cell, these make up the cone
|
||||||
for( int c : targetCells ){
|
for( int c : targetCells ){
|
||||||
Ballistica ray = new Ballistica(from, c, ballisticaParams);
|
Ballistica ray = new Ballistica(core.sourcePos, c, ballisticaParams);
|
||||||
cells.addAll(ray.subPath(1, ray.dist));
|
cells.addAll(ray.subPath(1, ray.dist));
|
||||||
rays.add(ray);
|
rays.add(ray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//lastly add any cells in the core
|
||||||
|
for ( int c : core.subPath(1, core.dist)){
|
||||||
|
if (Dungeon.level.trueDistance(core.sourcePos, c) <= maxDist){
|
||||||
|
cells.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user