v0.2.3: completed Dried Rose implementation
This commit is contained in:
parent
8ee4483004
commit
3ee8472e19
|
@ -4,6 +4,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
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.blobs.ToxicGas;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
|
@ -13,10 +14,12 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShaftParticle;
|
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShaftParticle;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.GhostSprite;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.GhostSprite;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlot;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
|
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
|
||||||
import com.watabou.noosa.audio.Sample;
|
import com.watabou.noosa.audio.Sample;
|
||||||
|
@ -52,6 +55,11 @@ public class DriedRose extends Artifact {
|
||||||
|
|
||||||
public static final String AC_SUMMON = "SUMMON";
|
public static final String AC_SUMMON = "SUMMON";
|
||||||
|
|
||||||
|
public DriedRose(){
|
||||||
|
super();
|
||||||
|
talkedTo = firstSummon = spawned = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<String> actions( Hero hero ) {
|
public ArrayList<String> actions( Hero hero ) {
|
||||||
ArrayList<String> actions = super.actions( hero );
|
ArrayList<String> actions = super.actions( hero );
|
||||||
|
@ -64,7 +72,7 @@ public class DriedRose extends Artifact {
|
||||||
public void execute( Hero hero, String action ) {
|
public void execute( Hero hero, String action ) {
|
||||||
if (action.equals(AC_SUMMON)) {
|
if (action.equals(AC_SUMMON)) {
|
||||||
|
|
||||||
if (spawned) GLog.n("sad ghost: I'm already here");
|
if (spawned) GLog.n("sad ghost: \"I'm already here\"");
|
||||||
else if (!isEquipped( hero )) GLog.i("You need to equip your rose to do that.");
|
else if (!isEquipped( hero )) GLog.i("You need to equip your rose to do that.");
|
||||||
else if (charge != chargeCap) GLog.i("Your rose isn't fully charged yet.");
|
else if (charge != chargeCap) GLog.i("Your rose isn't fully charged yet.");
|
||||||
else if (cursed) GLog.i("You cannot use a cursed rose.");
|
else if (cursed) GLog.i("You cannot use a cursed rose.");
|
||||||
|
@ -78,7 +86,7 @@ public class DriedRose extends Artifact {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spawnPoints.size() > 0) {
|
if (spawnPoints.size() > 0) {
|
||||||
GhostHero ghost = new GhostHero();
|
GhostHero ghost = new GhostHero( level );
|
||||||
ghost.pos = Random.element(spawnPoints);
|
ghost.pos = Random.element(spawnPoints);
|
||||||
|
|
||||||
GameScene.add(ghost, 1f);
|
GameScene.add(ghost, 1f);
|
||||||
|
@ -89,7 +97,15 @@ public class DriedRose extends Artifact {
|
||||||
hero.busy();
|
hero.busy();
|
||||||
hero.sprite.operate(hero.pos);
|
hero.sprite.operate(hero.pos);
|
||||||
|
|
||||||
|
if (!firstSummon) {
|
||||||
|
ghost.yell(ghost.VOICE_HELLO + Dungeon.hero.className());
|
||||||
|
Sample.INSTANCE.play( Assets.SND_GHOST );
|
||||||
|
firstSummon = true;
|
||||||
|
} else
|
||||||
|
ghost.saySpawned();
|
||||||
|
|
||||||
spawned = true;
|
spawned = true;
|
||||||
|
charge = 0;
|
||||||
} else
|
} else
|
||||||
GLog.i("There is no free space near you.");
|
GLog.i("There is no free space near you.");
|
||||||
}
|
}
|
||||||
|
@ -101,7 +117,28 @@ public class DriedRose extends Artifact {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String desc() {
|
public String desc() {
|
||||||
return "";
|
String desc =
|
||||||
|
"Is this the rose that the ghost mentioned before disappearing? It seems to hold some spiritual power,"+
|
||||||
|
" perhaps it can be used to channel the energy of that lost warrior.";
|
||||||
|
|
||||||
|
if (isEquipped( Dungeon.hero )){
|
||||||
|
if (!cursed){
|
||||||
|
desc += "\n\nThe rose rests in your hand, it feels strangely warm.";
|
||||||
|
|
||||||
|
if (level < 5)
|
||||||
|
desc+= "\n\nThe rose has lost most of its petals. It feels extremely frail, like it " +
|
||||||
|
"could snap any moment.";
|
||||||
|
else if (level < 10)
|
||||||
|
desc+= "\n\nYou have reattached many petals and the rose has started to somehow come back to life."+
|
||||||
|
" It almost looks like it's read to bloom.";
|
||||||
|
else
|
||||||
|
desc+= "\n\nThe rose has blossomed again through some kind of magic, its connection to your spirit"+
|
||||||
|
" friend is stronger than ever.";
|
||||||
|
} else
|
||||||
|
desc += "\n\nThe cursed rose is bound to you hand, it feels eerily cold.";
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -147,7 +184,7 @@ public class DriedRose extends Artifact {
|
||||||
|
|
||||||
if (charge < chargeCap && !cursed) {
|
if (charge < chargeCap && !cursed) {
|
||||||
//TODO: investigate balancing on this.
|
//TODO: investigate balancing on this.
|
||||||
partialCharge += 1/10f;
|
partialCharge += 10/75f;
|
||||||
if (partialCharge > 1){
|
if (partialCharge > 1){
|
||||||
charge++;
|
charge++;
|
||||||
partialCharge--;
|
partialCharge--;
|
||||||
|
@ -165,18 +202,20 @@ public class DriedRose extends Artifact {
|
||||||
if (Actor.findChar(p) == null && (Level.passable[p] || Level.avoid[p])) {
|
if (Actor.findChar(p) == null && (Level.passable[p] || Level.avoid[p])) {
|
||||||
spawnPoints.add(p);
|
spawnPoints.add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spawnPoints.size() > 0) {
|
|
||||||
Wraith wraith = new Wraith();
|
|
||||||
wraith.pos = Random.element(spawnPoints);
|
|
||||||
wraith.adjustStats(Dungeon.depth);
|
|
||||||
|
|
||||||
GameScene.add(wraith, 1f);
|
|
||||||
Sample.INSTANCE.play(Assets.SND_CURSED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spawnPoints.size() > 0) {
|
||||||
|
Wraith.spawnAt(Random.element(spawnPoints));
|
||||||
|
Sample.INSTANCE.play(Assets.SND_CURSED);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return super.act();
|
|
||||||
|
QuickSlot.refresh();
|
||||||
|
|
||||||
|
spend( TICK );
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +237,7 @@ public class DriedRose extends Artifact {
|
||||||
if (rose.level == rose.levelCap) {
|
if (rose.level == rose.levelCap) {
|
||||||
GLog.p("The rose is completed!");
|
GLog.p("The rose is completed!");
|
||||||
Sample.INSTANCE.play( Assets.SND_GHOST );
|
Sample.INSTANCE.play( Assets.SND_GHOST );
|
||||||
GLog.n("sad ghost: Thank you...");
|
GLog.n("sad ghost: \"Thank you...\"");
|
||||||
} else
|
} else
|
||||||
GLog.i("You add the petal to the rose.");
|
GLog.i("You add the petal to the rose.");
|
||||||
|
|
||||||
|
@ -223,10 +262,6 @@ public class DriedRose extends Artifact {
|
||||||
|
|
||||||
//TODO: needs to:
|
//TODO: needs to:
|
||||||
//have combat stats
|
//have combat stats
|
||||||
//attack only nearby enemies
|
|
||||||
//Be tethered to the player
|
|
||||||
//Enemies must be able/want to attack it
|
|
||||||
//Must be lost on level transition.
|
|
||||||
public static class GhostHero extends NPC {
|
public static class GhostHero extends NPC {
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -238,14 +273,48 @@ public class DriedRose extends Artifact {
|
||||||
state = WANDERING;
|
state = WANDERING;
|
||||||
enemy = DUMMY;
|
enemy = DUMMY;
|
||||||
|
|
||||||
|
ally = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GhostHero() {
|
public GhostHero() {
|
||||||
super();
|
super();
|
||||||
if (!DriedRose.firstSummon){
|
|
||||||
yell ( VOICE_HELLO );
|
//double heroes defence skill
|
||||||
DriedRose.firstSummon = true;
|
defenseSkill = (Dungeon.hero.lvl+4)*2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GhostHero(int roseLevel){
|
||||||
|
this();
|
||||||
|
HP = HT = 10+roseLevel*3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saySpawned(){
|
||||||
|
int i = (Dungeon.depth - 1) / 5;
|
||||||
|
if (chooseEnemy() == DUMMY)
|
||||||
|
yell( Random.element( VOICE_AMBIENT[i] ) );
|
||||||
|
else
|
||||||
|
yell( Random.element( VOICE_ENEMIES[i][ Dungeon.bossLevel() ? 1 : 0 ] ) );
|
||||||
|
Sample.INSTANCE.play( Assets.SND_GHOST );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sayAnhk(){
|
||||||
|
yell( Random.element( VOICE_BLESSEDANKH ) );
|
||||||
|
Sample.INSTANCE.play( Assets.SND_GHOST );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sayDefeated(){
|
||||||
|
yell( Random.element( VOICE_DEFEATED[ Dungeon.bossLevel() ? 1 : 0 ] ) );
|
||||||
|
Sample.INSTANCE.play( Assets.SND_GHOST );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sayHeroKilled(){
|
||||||
|
yell(Random.element(VOICE_HEROKILLED));
|
||||||
|
Sample.INSTANCE.play( Assets.SND_GHOST );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sayBossBeaten(){
|
||||||
|
yell( Random.element( VOICE_BOSSBEATEN[ Dungeon.depth==25 ? 1 : 0 ] ) );
|
||||||
|
Sample.INSTANCE.play( Assets.SND_GHOST );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -253,20 +322,34 @@ public class DriedRose extends Artifact {
|
||||||
return "evaded";
|
return "evaded";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean act() {
|
||||||
|
if (Random.Int(10) == 0) damage(1 , this);
|
||||||
|
if (!isAlive())
|
||||||
|
return true;
|
||||||
|
if (!Dungeon.hero.isAlive()){
|
||||||
|
sayHeroKilled();
|
||||||
|
sprite.die();
|
||||||
|
destroy();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.act();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean getCloser( int target ) {
|
protected boolean getCloser( int target ) {
|
||||||
if (state == WANDERING)
|
if (state == WANDERING || Level.distance(target, Dungeon.hero.pos) > 6)
|
||||||
this.target = target = Dungeon.hero.pos;
|
this.target = target = Dungeon.hero.pos;
|
||||||
return super.getCloser( target );
|
return super.getCloser( target );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Char chooseEnemy() {
|
protected Char chooseEnemy() {
|
||||||
if (enemy == DUMMY || !enemy.isAlive()) {
|
if (enemy == DUMMY || !enemy.isAlive() || state == WANDERING) {
|
||||||
|
|
||||||
HashSet<Mob> enemies = new HashSet<Mob>();
|
HashSet<Mob> enemies = new HashSet<Mob>();
|
||||||
for (Mob mob : Dungeon.level.mobs) {
|
for (Mob mob : Dungeon.level.mobs) {
|
||||||
if (mob.hostile && Level.fieldOfView[mob.pos]) {
|
if (mob.hostile && Level.fieldOfView[mob.pos] && mob.state != mob.PASSIVE) {
|
||||||
enemies.add(mob);
|
enemies.add(mob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,11 +359,27 @@ public class DriedRose extends Artifact {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void damage( int dmg, Object src ) {
|
public int attackSkill(Char target) {
|
||||||
|
//same accuracy as the hero.
|
||||||
|
return (defenseSkill/2)+5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int damageRoll() {
|
||||||
|
//equivalent to N/2 to 5+N, where N is rose level.
|
||||||
|
int lvl = (HT-10)/3;
|
||||||
|
return Random.NormalIntRange( lvl/2, 5+lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int dr() {
|
||||||
|
//defence is equal to the level of rose.
|
||||||
|
return (HT-10)/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add( Buff buff ) {
|
public void add( Buff buff ) {
|
||||||
|
//in other words, can't be directly affected by buffs/debuffs.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -302,32 +401,47 @@ public class DriedRose extends Artifact {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void die(Object cause) {
|
||||||
|
sayDefeated();
|
||||||
|
super.die(cause);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
DriedRose.spawned = false;
|
DriedRose.spawned = false;
|
||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return
|
||||||
|
"A frail looking ethereal figure with a humanoid shape. Its power seems tied to the rose I have." +
|
||||||
|
"\n\nThis ghost may not be much, but it seems to be my only true friend down here.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||||
|
static {
|
||||||
|
IMMUNITIES.add( ToxicGas.class );
|
||||||
|
IMMUNITIES.add( ScrollOfPsionicBlast.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashSet<Class<?>> immunities() {
|
||||||
|
return IMMUNITIES;
|
||||||
|
}
|
||||||
|
|
||||||
//************************************************************************************
|
//************************************************************************************
|
||||||
//This is a bunch strings & string arrays, used in all of the sad ghost's voice lines.
|
//This is a bunch strings & string arrays, used in all of the sad ghost's voice lines.
|
||||||
//************************************************************************************
|
//************************************************************************************
|
||||||
|
|
||||||
public static final String VOICE_HELLO = "Hello again.";
|
public static final String VOICE_HELLO = "Hello again ";
|
||||||
|
|
||||||
private static final String VOICE_INTRODUCE = "My spirit is bound to this rose, it was very precious to me, a "+
|
private static final String VOICE_INTRODUCE = "My spirit is bound to this rose, it was very precious to me, a "+
|
||||||
"gift from my love whom I left on the surface.\n\nI cannot return to him, but thanks to you I have a " +
|
"gift from my love whom I left on the surface.\n\nI cannot return to him, but thanks to you I have a " +
|
||||||
"second chance to complete my journey. When I am able I will respond to your call and fight with you.\n\n" +
|
"second chance to complete my journey. When I am able I will respond to your call and fight with you.\n\n" +
|
||||||
"hopefully you may succeed where I failed...";
|
"hopefully you may succeed where I failed...";
|
||||||
|
|
||||||
//enum, for clarity.
|
|
||||||
public static enum DEPTHS{
|
|
||||||
SEWERS,
|
|
||||||
PRISON,
|
|
||||||
CAVES,
|
|
||||||
CITY,
|
|
||||||
HALLS,
|
|
||||||
AMULET
|
|
||||||
}
|
|
||||||
|
|
||||||
//1st index - depth type, 2nd index - specific line.
|
//1st index - depth type, 2nd index - specific line.
|
||||||
public static final String[][] VOICE_AMBIENT = {
|
public static final String[][] VOICE_AMBIENT = {
|
||||||
{
|
{
|
||||||
|
@ -409,7 +523,7 @@ public class DriedRose extends Artifact {
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
{
|
{
|
||||||
"Hello source viewer, I'm writing this here as this line should never trigger. Have a nice day!"
|
"I don't like this place... we should leave as soon as we can..."
|
||||||
},{
|
},{
|
||||||
"Hello source viewer, I'm writing this here as this line should never trigger. Have a nice day!"
|
"Hello source viewer, I'm writing this here as this line should never trigger. Have a nice day!"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user