v0.8.0: rough implementation for Yog's fists and Yog fight progression

This commit is contained in:
Evan Debenham 2020-03-10 15:51:10 -04:00
parent b1f7023d78
commit 3c4e8a5f74
10 changed files with 872 additions and 23 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -40,6 +40,10 @@ public class Bleeding extends Buff {
protected float level;
public float level(){
return level;
}
private static final String LEVEL = "level";
@Override

View File

@ -57,6 +57,10 @@ public class Light extends FlavourBuff {
super.detach();
}
public void weaken( int amount ){
spend(-amount);
}
@Override
public int icon() {
return BuffIndicator.LIGHT;

View File

@ -21,23 +21,213 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.LockedFloor;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetribution;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Grim;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.FistSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.LarvaSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.YogSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.BossHealthBar;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
import com.watabou.utils.Reflection;
//TODO boss implementation
public class YogDzewa extends Yog {
import java.util.ArrayList;
import java.util.Collection;
public class YogDzewa extends Mob {
{
HP = HT = 1;
spriteClass = YogSprite.class;
HP = HT = 600;
EXP = 50;
state = PASSIVE;
properties.add(Property.BOSS);
properties.add(Property.IMMOVABLE);
properties.add(Property.DEMONIC);
}
private int phase = 0;
private Class[] toSummon = new Class[3];
{
toSummon[0] = (Random.Int(2) == 0 ? YogFist.Burning.class : YogFist.Soiled.class);
toSummon[1] = (Random.Int(2) == 0 ? YogFist.Rotting.class : YogFist.Rusted.class);
toSummon[2] = (Random.Int(2) == 0 ? YogFist.Bright.class : YogFist.Dark.class);
Random.shuffle(toSummon);
}
@Override
public void damage( int dmg, Object src ) {
if (findFist() != null){
sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "immune"));
return;
}
super.damage( dmg, src );
if (phase < 3 && HP <= HT * (3 - phase)/4f){
Dungeon.level.viewDistance--;
if (Dungeon.hero.buff(Light.class) == null){
Dungeon.hero.viewDistance = Dungeon.level.viewDistance;
}
Dungeon.observe();
GLog.n(Messages.get(this, "darkness"));
sprite.showStatus(CharSprite.POSITIVE, Messages.get(this, "immune"));
YogFist fist = (YogFist) Reflection.newInstance(toSummon[phase]);
fist.pos = Dungeon.level.exit;
//TODO change based on what fist is summoned?
CellEmitter.get(Dungeon.level.exit-1).burst(ShadowParticle.UP, 25);
CellEmitter.get(Dungeon.level.exit).burst(ShadowParticle.UP, 100);
CellEmitter.get(Dungeon.level.exit+1).burst(ShadowParticle.UP, 25);
int targetPos = Dungeon.level.exit + Dungeon.level.width();
if (Actor.findChar(targetPos) == null){
fist.pos = targetPos;
} else if (Actor.findChar(targetPos-1) == null){
fist.pos = targetPos-1;
} else if (Actor.findChar(targetPos+1) == null){
fist.pos = targetPos+1;
}
GameScene.add(fist, 1);
Actor.addDelayed( new Pushing( fist, Dungeon.level.exit, fist.pos ), -1 );
phase++;
}
LockedFloor lock = Dungeon.hero.buff(LockedFloor.class);
if (lock != null) lock.addTime(dmg);
}
private YogFist findFist(){
for ( Char c : Actor.chars() ){
if (c instanceof YogFist){
return (YogFist) c;
}
}
return null;
}
@Override
public void beckon( int cell ) {
}
@SuppressWarnings("unchecked")
@Override
public void die( Object cause ) {
for (Mob mob : (Iterable<Mob>)Dungeon.level.mobs.clone()) {
if (mob instanceof Larva || mob instanceof RipperDemon) {
mob.die( cause );
}
}
Dungeon.level.viewDistance = 4;
if (Dungeon.hero.buff(Light.class) == null){
Dungeon.hero.viewDistance = Dungeon.level.viewDistance;
}
GameScene.bossSlain();
Dungeon.level.unseal();
super.die( cause );
Dungeon.level.unseal();
Dungeon.level.heaps.get(pos).destroy();
yell( Messages.get(this, "defeated") );
}
@Override
public void notice() {
super.notice();
if (!BossHealthBar.isAssigned()) {
BossHealthBar.assignBoss(this);
yell(Messages.get(this, "notice"));
for (Char ch : Actor.chars()){
if (ch instanceof DriedRose.GhostHero){
GLog.n("\n");
((DriedRose.GhostHero) ch).sayBoss();
}
}
}
}
{
immunities.add( Grim.class );
immunities.add( GrimTrap.class );
immunities.add( Terror.class );
immunities.add( Amok.class );
immunities.add( Charm.class );
immunities.add( Sleep.class );
immunities.add( Burning.class );
immunities.add( ToxicGas.class );
immunities.add( ScrollOfRetribution.class );
immunities.add( ScrollOfPsionicBlast.class );
immunities.add( Vertigo.class );
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
BossHealthBar.assignBoss(this);
}
public static class Larva extends Mob {
{
spriteClass = LarvaSprite.class;
HP = HT = 25;
defenseSkill = 20;
EXP = 5;
maxLvl = -2;
state = HUNTING;
properties.add(Property.DEMONIC);
}
@Override
public int attackSkill( Char target ) {
return 30;
}
@Override
public int damageRoll() {
return Random.NormalIntRange( 22, 30 );
}
@Override
public int drRoll() {
return Random.NormalIntRange(0, 8);
}
}
}

View File

@ -0,0 +1,522 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2020 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.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Viscosity;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.FistSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
public abstract class YogFist extends Mob {
{
HP = HT = 300;
defenseSkill = 25;
//for doomed resistance
EXP = 25;
maxLvl = -2;
state = WANDERING;
properties.add(Property.BOSS);
properties.add(Property.DEMONIC);
}
private float rangedCooldown;
protected boolean canRangedInMelee = true;
protected void incrementRangedCooldown(){
rangedCooldown += Random.NormalFloat(6, 9);
}
@Override
protected boolean act() {
if (paralysed <= 0 && rangedCooldown > 0) rangedCooldown--;
return super.act();
}
@Override
protected boolean canAttack(Char enemy) {
if (rangedCooldown <= 0){
return new Ballistica( pos, enemy.pos, Ballistica.MAGIC_BOLT).collisionPos == enemy.pos;
} else {
return super.canAttack(enemy);
}
}
@Override
protected boolean doAttack( Char enemy ) {
if (Dungeon.level.adjacent( pos, enemy.pos ) && (!canRangedInMelee || rangedCooldown > 0)) {
return super.doAttack( enemy );
} else {
incrementRangedCooldown();
if (sprite != null && (sprite.visible || enemy.sprite.visible)) {
sprite.zap( enemy.pos );
return false;
} else {
zap();
return true;
}
}
}
protected abstract void zap();
public void onZapComplete(){
zap();
next();
}
@Override
public int attackSkill( Char target ) {
return 36;
}
@Override
//TODO different for some fists perhaps?
public int damageRoll() {
return Random.NormalIntRange( 26, 32 );
}
@Override
public int drRoll() {
return Random.NormalIntRange(0, 15);
}
public static class Burning extends YogFist {
{
spriteClass = FistSprite.Burning.class;
properties.add(Property.FIERY);
}
@Override
public boolean act() {
boolean result = super.act();
if (Dungeon.level.map[pos] == Terrain.WATER){
Level.set( pos, Terrain.EMPTY);
GameScene.updateMap( pos );
CellEmitter.get( pos ).burst( Speck.factory( Speck.STEAM ), 10 );
}
for (int i = 0; i < 2; i++){
int cell = pos + PathFinder.NEIGHBOURS8[Random.Int(8)];
if (Dungeon.level.map[cell] == Terrain.WATER){
Level.set( cell, Terrain.EMPTY);
GameScene.updateMap( cell );
CellEmitter.get( cell ).burst( Speck.factory( Speck.STEAM ), 10 );
}
}
for (int i : PathFinder.NEIGHBOURS9) {
int vol = Fire.volumeAt(pos+i, Fire.class);
if (vol < 4 && !Dungeon.level.water[pos + i] && !Dungeon.level.solid[pos + i]){
GameScene.add( Blob.seed( pos + i, 4 - vol, Fire.class ) );
}
}
return result;
}
@Override
protected void zap() {
spend( 1f );
if (hit( this, enemy, true )) {
int dmg = damageRoll()/2;
//TODO damage source logic
enemy.damage( dmg, this );
Buff.affect( enemy, com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning.class ).reignite( enemy );
if (!enemy.isAlive() && enemy == Dungeon.hero) {
Dungeon.fail( getClass() );
GLog.n( Messages.get(Char.class, "kill", name()) );
}
} else {
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
}
if (Dungeon.level.map[enemy.pos] == Terrain.WATER){
Level.set( enemy.pos, Terrain.EMPTY);
GameScene.updateMap( enemy.pos );
CellEmitter.get( enemy.pos ).burst( Speck.factory( Speck.STEAM ), 10 );
}
for (int i : PathFinder.NEIGHBOURS9){
if (!Dungeon.level.water[enemy.pos+i] && !Dungeon.level.solid[enemy.pos+i]){
int vol = Fire.volumeAt(enemy.pos+i, Fire.class);
if (vol < 4){
GameScene.add( Blob.seed( enemy.pos + i, 4 - vol, Fire.class ) );
}
}
}
}
}
public static class Soiled extends YogFist {
{
spriteClass = FistSprite.Soiled.class;
}
@Override
public boolean act() {
boolean result = super.act();
for (int i = 0; i < 2; i++){
int cell = pos + PathFinder.NEIGHBOURS9[Random.Int(9)];
if (Dungeon.level.map[cell] == Terrain.GRASS){
Level.set( cell, Terrain.FURROWED_GRASS);
GameScene.updateMap( cell );
CellEmitter.get( cell ).burst( LeafParticle.GENERAL, 10 );
}
}
Dungeon.observe();
for (int i : PathFinder.NEIGHBOURS9) {
int cell = pos + i;
if (canSpreadGrass(cell)){
Level.set(pos+i, Terrain.GRASS);
GameScene.updateMap( pos + i );
}
}
return result;
}
@Override
public void damage(int dmg, Object src) {
int grassCells = 0;
for (int i : PathFinder.NEIGHBOURS9) {
if (Dungeon.level.map[pos+i] == Terrain.FURROWED_GRASS
|| Dungeon.level.map[pos+i] == Terrain.HIGH_GRASS){
grassCells++;
}
}
if (grassCells > 0) dmg = Math.round(dmg * (9-grassCells)/9f);
super.damage(dmg, src);
}
@Override
protected void zap() {
spend( 1f );
if (hit( this, enemy, true )) {
int dmg = damageRoll()/2;
//TODO damage source logic
enemy.damage( dmg, this );
Buff.affect( enemy, Roots.class, 3f );
if (!enemy.isAlive() && enemy == Dungeon.hero) {
Dungeon.fail( getClass() );
GLog.n( Messages.get(Char.class, "kill", name()) );
}
} else {
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
}
for (int i : PathFinder.NEIGHBOURS9){
int cell = enemy.pos + i;
if (canSpreadGrass(cell)){
if (Random.Int(5) == 0){
Level.set(cell, Terrain.FURROWED_GRASS);
GameScene.updateMap( cell );
} else {
Level.set(cell, Terrain.GRASS);
GameScene.updateMap( cell );
}
CellEmitter.get( cell ).burst( LeafParticle.GENERAL, 10 );
}
}
Dungeon.observe();
}
private boolean canSpreadGrass(int cell){
int yogPos = Dungeon.level.exit + Dungeon.level.width()*3;
return Dungeon.level.distance(cell, yogPos) > 4 && !Dungeon.level.solid[cell]
&& !(Dungeon.level.map[cell] == Terrain.FURROWED_GRASS || Dungeon.level.map[cell] == Terrain.HIGH_GRASS);
}
}
public static class Rotting extends YogFist {
{
spriteClass = FistSprite.Rotting.class;
properties.add(Property.ACIDIC);
}
@Override
protected boolean act() {
//ensures toxic gas acts at the appropriate time when added
GameScene.add(Blob.seed(pos, 0, ToxicGas.class));
if (Dungeon.level.water[pos] && HP < HT) {
sprite.emitter().burst( Speck.factory(Speck.HEALING), 3 );
HP += HT/50;
}
return super.act();
}
@Override
public void damage(int dmg, Object src) {
if (!(src instanceof Bleeding)){
Bleeding b = buff(Bleeding.class);
if (b == null){
b = new Bleeding();
}
b.announced = false;
b.set(dmg/3f);
b.attachTo(this);
sprite.showStatus(CharSprite.WARNING, b.toString() + " " + (int)b.level());
} else{
super.damage(dmg, src);
}
}
@Override
protected void zap() {
spend( 1f );
GameScene.add(Blob.seed(enemy.pos, 100, ToxicGas.class));
}
@Override
public int attackProc( Char enemy, int damage ) {
damage = super.attackProc( enemy, damage );
if (Random.Int( 2 ) == 0) {
Buff.affect( enemy, Ooze.class ).set( 20f );
enemy.sprite.burst( 0xFF000000, 5 );
}
return damage;
}
{
immunities.add(ToxicGas.class);
}
}
public static class Rusted extends YogFist {
{
spriteClass = FistSprite.Rusted.class;
properties.add(Property.LARGE);
properties.add(Property.INORGANIC);
}
@Override
public void damage(int dmg, Object src) {
if (!(src instanceof Viscosity.DeferedDamage)){
Buff.affect(this, Viscosity.DeferedDamage.class).prolong(dmg);
sprite.showStatus( CharSprite.WARNING, Messages.get(Viscosity.class, "deferred", dmg) );
} else{
super.damage(dmg, src);
}
}
@Override
protected void zap() {
spend( 1f );
Buff.affect(enemy, Cripple.class, 5f);
}
}
public static class Bright extends YogFist {
{
spriteClass = FistSprite.Bright.class;
properties.add(Property.ELECTRIC);
canRangedInMelee = false;
}
@Override
protected void incrementRangedCooldown() {
//ranged attack has no cooldown
}
@Override
protected void zap() {
spend( 1f );
if (hit( this, enemy, true )) {
int dmg = damageRoll()/2;
//TODO damage source logic
enemy.damage( dmg, this );
Buff.prolong( enemy, Blindness.class, 5f );
if (!enemy.isAlive() && enemy == Dungeon.hero) {
Dungeon.fail( getClass() );
GLog.n( Messages.get(Char.class, "kill", name()) );
}
} else {
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
}
}
@Override
public void damage(int dmg, Object src) {
int beforeHP = HP;
super.damage(dmg, src);
if (beforeHP > HT/2 && HP < HT/2){
HP = HT/2;
Buff.prolong( enemy, Blindness.class, 50f );
int i;
do {
i = Random.Int(Dungeon.level.length());
} while (Dungeon.level.heroFOV[i] || Dungeon.level.solid[i] || Actor.findChar(i) != null);
ScrollOfTeleportation.appear(this, i);
state = WANDERING;
GameScene.flash(0xFFFFFF);
} else if (!isAlive()){
Buff.prolong( enemy, Blindness.class, 50f );
GameScene.flash(0xFFFFFF);
}
}
}
public static class Dark extends YogFist {
{
spriteClass = FistSprite.Dark.class;
canRangedInMelee = false;
}
@Override
protected void incrementRangedCooldown() {
//ranged attack has no cooldown
}
@Override
protected void zap() {
spend( 1f );
if (hit( this, enemy, true )) {
int dmg = damageRoll()/2;
//TODO damage source logic
enemy.damage( dmg, this );
Light l = enemy.buff(Light.class);
if (l != null){
l.weaken(50);
}
if (!enemy.isAlive() && enemy == Dungeon.hero) {
Dungeon.fail( getClass() );
GLog.n( Messages.get(Char.class, "kill", name()) );
}
} else {
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
}
}
@Override
public void damage(int dmg, Object src) {
int beforeHP = HP;
super.damage(dmg, src);
if (beforeHP > HT/2 && HP < HT/2){
HP = HT/2;
Light l = Dungeon.hero.buff(Light.class);
if (l != null){
l.detach();
}
int i;
do {
i = Random.Int(Dungeon.level.length());
} while (Dungeon.level.heroFOV[i] || Dungeon.level.solid[i] || Actor.findChar(i) != null);
ScrollOfTeleportation.appear(this, i);
state = WANDERING;
GameScene.flash(0, false);
} else if (!isAlive()){
Light l = Dungeon.hero.buff(Light.class);
if (l != null){
l.detach();
}
GameScene.flash(0, false);
}
}
}
}

View File

@ -45,6 +45,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.YogFist;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Sheep;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlowParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.WindParticle;
@ -951,7 +952,8 @@ public abstract class Level implements Bundlable {
if (sighted) {
boolean[] blocking;
if (c instanceof Hero && ((Hero) c).subClass == HeroSubClass.WARDEN) {
if ((c instanceof Hero && ((Hero) c).subClass == HeroSubClass.WARDEN)
|| c instanceof YogFist.Soiled) {
blocking = Dungeon.level.losBlocking.clone();
for (int i = 0; i < blocking.length; i++){
if (blocking[i] && (Dungeon.level.map[i] == Terrain.HIGH_GRASS || Dungeon.level.map[i] == Terrain.FURROWED_GRASS)){

View File

@ -27,7 +27,6 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.YogDzewa;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
@ -164,7 +163,7 @@ public class NewHallsBossLevel extends Level {
if (item != null) {
int pos;
do {
pos = Random.IntRange( ROOM_LEFT, ROOM_RIGHT ) + Random.IntRange( ROOM_TOP + 1, ROOM_BOTTOM ) * width();
pos = randomRespawnCell(null);
} while (pos == entrance);
drop( item, pos ).setHauntedIfCursed().type = Heap.Type.REMAINS;
}
@ -201,10 +200,9 @@ public class NewHallsBossLevel extends Level {
Dungeon.observe();
Yog boss = new YogDzewa();
YogDzewa boss = new YogDzewa();
boss.pos = exit + width*3;
GameScene.add( boss );
//boss.spawnFists();
}
@Override
@ -218,7 +216,6 @@ public class NewHallsBossLevel extends Level {
CellEmitter.get(exit-1).burst(ShadowParticle.UP, 25);
CellEmitter.get(exit).burst(ShadowParticle.UP, 100);
CellEmitter.get(exit+1).burst(ShadowParticle.UP, 25);
GameScene.flash(0);
for( CustomTilemap t : customTiles){
if (t instanceof CenterPieceVisuals){
((CenterPieceVisuals) t).updateState();

View File

@ -932,7 +932,11 @@ public class GameScene extends PixelScene {
}
public static void flash( int color ) {
scene.fadeIn( 0xFF000000 | color, true );
flash( color, true);
}
public static void flash( int color, boolean lightmode ) {
scene.fadeIn( 0xFF000000 | color, lightmode );
}
public static void gameOver() {

View File

@ -24,9 +24,16 @@ package com.shatteredpixel.shatteredpixeldungeon.sprites;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.YogFist;
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.CorrosionParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
import com.shatteredpixel.shatteredpixeldungeon.levels.SewerLevel;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SparkParticle;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.watabou.noosa.Camera;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.audio.Sample;
@ -124,7 +131,12 @@ public abstract class FistSprite extends MobSprite {
new Callback() {
@Override
public void call() {
//pre-0.8.0 saves
if (ch instanceof Yog.BurningFist){
((Yog.BurningFist)ch).onZapComplete();
} else {
((YogFist)ch).onZapComplete();
}
}
} );
Sample.INSTANCE.play( Assets.SND_ZAP );
@ -160,12 +172,35 @@ public abstract class FistSprite extends MobSprite {
@Override
public int blood() {
return 0xFFFFBB33;
return 0xFFFFDD34;
}
}
///
public static class Soiled extends FistSprite {
{
boltType = MagicMissile.FOLIAGE;
}
@Override
protected int texOffset() {
return 10;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour( LeafParticle.GENERAL, 0.06f );
return emitter;
}
@Override
public int blood() {
return 0xFF7F5424;
}
}
public static class Rotting extends FistSprite {
@ -181,13 +216,96 @@ public abstract class FistSprite extends MobSprite {
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
//emitter.pour( SewerLevel.WaterParticle.FACTORY, 0.06f );
emitter.pour(Speck.factory(Speck.TOXIC), 0.25f );
return emitter;
}
@Override
public int blood() {
return 0xFFFFBB33;
return 0xFFB8BBA1;
}
}
public static class Rusted extends FistSprite {
{
boltType = MagicMissile.CORROSION;
}
@Override
protected int texOffset() {
return 30;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour(CorrosionParticle.MISSILE, 0.06f );
return emitter;
}
@Override
public int blood() {
return 0xFF7F7F7F;
}
}
public static class Bright extends FistSprite {
{
boltType = MagicMissile.RAINBOW;
}
@Override
protected int texOffset() {
return 40;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour(SparkParticle.STATIC, 0.06f );
return emitter;
}
@Override
public void zap( int cell ) {
turnTo( ch.pos , cell );
play( zap );
((YogFist)ch).onZapComplete();
parent.add( new Beam.LightRay(center(), DungeonTilemap.raisedTileCenterToWorld(cell)));
}
@Override
public int blood() {
return 0xFFFFFFFF;
}
}
public static class Dark extends FistSprite {
{
boltType = MagicMissile.SHADOW;
}
@Override
protected int texOffset() {
return 50;
}
@Override
protected Emitter createEmitter() {
Emitter emitter = emitter();
emitter.pour(ShadowParticle.MISSILE, 0.06f );
return emitter;
}
@Override
public int blood() {
return 0xFF4A2F53;
}
}

View File

@ -740,6 +740,14 @@ actors.mobs.yog$larva.name=god's larva
actors.mobs.yog$larva.rankings_desc=Devoured by Yog-Dzewa
actors.mobs.yog$larva.desc=Yog-Dzewa is an Old God, a powerful entity from the realms of chaos. A century ago, the ancient dwarves barely won the war against its army of demons, but were unable to kill the god itself. Instead, they then imprisoned it in the halls below their city, believing it to be too weak to rise ever again.
actors.mobs.yogdzewa.name=Yog-Dzewa
actors.mobs.yogdzewa.notice=I. SEE. YOU.
actors.mobs.yogdzewa.immune=IMMUNE
actors.mobs.yogdzewa.darkness=The shadows pull in closer.
actors.mobs.yogdzewa.defeated=...
actors.mobs.yogdzewa.rankings_desc=Devoured by Yog-Dzewa
actors.mobs.yogdzewa.desc=TODO
actors.char.kill=%s killed you...