v2.5.0: added a new very rare cursed wand effect: supernova!
This commit is contained in:
@@ -1397,6 +1397,8 @@ items.wands.cursedwand.fire=You smell burning...
|
||||
items.wands.cursedwand.transmogrify_wand=Your wand transmogrifies into a different item!
|
||||
items.wands.cursedwand.transmogrify_other=Your item transmogrifies into something different!
|
||||
items.wands.cursedwand.disguise=Your appearance changes before your eyes!
|
||||
items.wands.cursedwand.supernova=A blazing ball of energy starts to grow. You might want to run!
|
||||
items.wands.cursedwand.supernova_positive=A blazing ball of energy starts to grow, but it feels safe somehow.
|
||||
|
||||
items.wands.damagewand.upgrade_stat_name_1=Magic Damage
|
||||
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2024 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.actors.buffs;
|
||||
|
||||
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.effects.FloatingText;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.TargetedCell;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bombs.Bomb;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.ShadowCaster;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.Halo;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.PointF;
|
||||
|
||||
public class SuperNovaTracker extends Buff {
|
||||
|
||||
public int pos;
|
||||
private int depth = Dungeon.depth;
|
||||
private int branch = Dungeon.branch;
|
||||
|
||||
private int turnsLeft = 10;
|
||||
public boolean harmsAllies = true;
|
||||
|
||||
private boolean[] fieldOfView;
|
||||
private NovaVFX halo;
|
||||
|
||||
private static final int DIST = 8;
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
|
||||
if (branch != Dungeon.branch || depth != Dungeon.depth){
|
||||
spend(TICK);
|
||||
return true;
|
||||
}
|
||||
|
||||
PointF p = DungeonTilemap.raisedTileCenterToWorld(pos);
|
||||
if (fieldOfView == null){
|
||||
fieldOfView = new boolean[Dungeon.level.length()];
|
||||
}
|
||||
if (halo == null){
|
||||
halo = new NovaVFX();
|
||||
halo.point(p.x, p.y);
|
||||
halo.hardlight(1, 1, 0f);
|
||||
GameScene.effect(halo);
|
||||
}
|
||||
|
||||
if (turnsLeft > 0){
|
||||
|
||||
FloatingText.show(p.x, p.y, pos, turnsLeft + "...", CharSprite.WARNING);
|
||||
halo.radius(5 + 2*(10-turnsLeft));
|
||||
halo.alpha(1.25f - 0.075f*turnsLeft);
|
||||
halo.point(p.x, p.y);
|
||||
}
|
||||
|
||||
Point c = Dungeon.level.cellToPoint(pos);
|
||||
ShadowCaster.castShadow(c.x, c.y, Dungeon.level.width(), fieldOfView, Dungeon.level.solid, Math.min(DIST, 11-turnsLeft));
|
||||
|
||||
if (turnsLeft <= 0){
|
||||
detach();
|
||||
halo.killAndErase();
|
||||
|
||||
//if positive only, bombs do not harm allies
|
||||
if (!harmsAllies) {
|
||||
for (Char ch : Actor.chars()) {
|
||||
if (ch.alignment == Char.Alignment.ALLY) {
|
||||
Buff.affect(ch, NovaBombImmune.class, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sample.INSTANCE.play(Assets.Sounds.BLAST);
|
||||
Sample.INSTANCE.playDelayed(Assets.Sounds.BLAST, 0.25f);
|
||||
Sample.INSTANCE.playDelayed(Assets.Sounds.BLAST, 0.5f);
|
||||
PixelScene.shake( 5, 2f );
|
||||
for (int i = 0; i < Dungeon.level.length(); i++){
|
||||
if (fieldOfView[i]){
|
||||
new Bomb.ConjuredBomb().explode(i); //yes, a bomb at every cell
|
||||
//this means that something in the blast effectively takes:
|
||||
//5.33x bomb dmg when fully inside
|
||||
//4.33x when along straight edge
|
||||
//2x when outside straight edge
|
||||
Dungeon.level.destroy(i);
|
||||
if (Actor.findChar(i) == Dungeon.hero){
|
||||
GameScene.flash(0x80FFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
GameScene.updateMap();
|
||||
|
||||
} else {
|
||||
for (int i = 0; i < Dungeon.level.length(); i++){
|
||||
if (fieldOfView[i]){
|
||||
target.sprite.parent.add(new TargetedCell(i, 0xFF0000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
turnsLeft--;
|
||||
spend(TICK);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public static class NovaBombImmune extends FlavourBuff{
|
||||
{
|
||||
immunities.add(Bomb.ConjuredBomb.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fx(boolean on) {
|
||||
if (on && depth == Dungeon.depth && branch == Dungeon.branch
|
||||
&& (halo == null || halo.parent == null)){
|
||||
halo = new NovaVFX();
|
||||
PointF p = DungeonTilemap.raisedTileCenterToWorld(pos);
|
||||
halo.hardlight(1, 1, 0f);
|
||||
halo.radius(5 + 2*(10-turnsLeft));
|
||||
halo.alpha(1.25f - 0.075f*turnsLeft);
|
||||
halo.point(p.x, p.y);
|
||||
GameScene.effect(halo);
|
||||
}
|
||||
super.fx(on);
|
||||
}
|
||||
|
||||
public static final String POS = "pos";
|
||||
public static final String DEPTH = "depth";
|
||||
public static final String BRANCH = "branch";
|
||||
|
||||
public static final String LEFT = "left";
|
||||
public static final String HARMS_ALLIES = "harms_allies";
|
||||
|
||||
@Override
|
||||
public void storeInBundle(Bundle bundle) {
|
||||
super.storeInBundle(bundle);
|
||||
bundle.put(POS, pos);
|
||||
bundle.put(DEPTH, depth);
|
||||
bundle.put(BRANCH, branch);
|
||||
bundle.put(LEFT, turnsLeft);
|
||||
bundle.put(HARMS_ALLIES, harmsAllies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
pos = bundle.getInt(POS);
|
||||
depth = bundle.getInt(DEPTH);
|
||||
branch = bundle.getInt(BRANCH);
|
||||
turnsLeft = bundle.getInt(LEFT);
|
||||
harmsAllies = bundle.getBoolean(HARMS_ALLIES);
|
||||
}
|
||||
|
||||
public class NovaVFX extends Halo {
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
am = brightness + 0.1f*(float)Math.cos(20*Game.timeTotal);
|
||||
scale.set((radius + (float)Math.cos(20*Game.timeTotal))/RADIUS);
|
||||
PointF p = DungeonTilemap.raisedTileCenterToWorld(pos);
|
||||
point(p.x, p.y);
|
||||
super.update();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,6 +42,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.HeroDisguise;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hex;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Recharging;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.SuperNovaTracker;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GoldenMimic;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||
@@ -586,6 +587,7 @@ public class CursedWand {
|
||||
VERY_RARE_EFFECTS.add(new AbortRetryFail());
|
||||
VERY_RARE_EFFECTS.add(new RandomTransmogrify());
|
||||
VERY_RARE_EFFECTS.add(new HeroShapeShift());
|
||||
VERY_RARE_EFFECTS.add(new SuperNova());
|
||||
}
|
||||
|
||||
public static CursedEffect randomVeryRareEffect(){
|
||||
@@ -759,7 +761,7 @@ public class CursedWand {
|
||||
}
|
||||
}
|
||||
|
||||
public static class HeroShapeShift extends CursedEffect{
|
||||
public static class HeroShapeShift extends CursedEffect {
|
||||
|
||||
@Override
|
||||
public boolean valid(Item origin, Char user, Ballistica bolt, boolean positiveOnly) {
|
||||
@@ -781,4 +783,20 @@ public class CursedWand {
|
||||
}
|
||||
}
|
||||
|
||||
public static class SuperNova extends CursedEffect {
|
||||
@Override
|
||||
public boolean effect(Item origin, Char user, Ballistica bolt, boolean positiveOnly) {
|
||||
SuperNovaTracker nova = Buff.append(Dungeon.hero, SuperNovaTracker.class);
|
||||
nova.pos = bolt.collisionPos;
|
||||
nova.harmsAllies = !positiveOnly;
|
||||
if (positiveOnly){
|
||||
GLog.p(Messages.get(CursedWand.class, "supernova_positive"));
|
||||
} else {
|
||||
GLog.w(Messages.get(CursedWand.class, "supernova"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user