v0.3.2: lots of wandmaker quest implementation
This commit is contained in:
parent
cf2c54d115
commit
c3ea21d5f4
|
@ -21,9 +21,12 @@
|
||||||
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
|
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.quest.CeremonialCandle;
|
||||||
import com.watabou.noosa.audio.Sample;
|
import com.watabou.noosa.audio.Sample;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
@ -62,24 +65,58 @@ public class Wandmaker extends NPC {
|
||||||
name = "old wandmaker";
|
name = "old wandmaker";
|
||||||
spriteClass = WandmakerSprite.class;
|
spriteClass = WandmakerSprite.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String TXT_BERRY1 =
|
private static final String INTRO_WARRIOR =
|
||||||
"Oh, what a pleasant surprise to meet a decent person in such place! I came here for a rare ingredient - " +
|
"Oh, what a pleasant surprise to meet a hero in such a depressing place! " +
|
||||||
"a _Rotberry seed_. Being a magic user, I'm quite able to defend myself against local monsters, " +
|
"If you're up to helping an old man out, I may have a task for you.\n\n";
|
||||||
"but I'm getting lost in no time, it's very embarrassing. Probably you could help me? I would be " +
|
|
||||||
"happy to pay for your service with one of my best wands.";
|
private static final String INTRO_ROGUE =
|
||||||
|
"Oh Goodness, you startled me! I haven't met a bandit from this place that still has his sanity, " +
|
||||||
private static final String TXT_DUST1 =
|
"so you must be from the surface! If you're up to helping a stranger out, I may have a task for you.\n\n";
|
||||||
"Oh, what a pleasant surprise to meet a decent person in such place! I came here for a rare ingredient - " +
|
|
||||||
"_corpse dust_. It can be gathered from skeletal remains and there is an ample number of them in the dungeon. " +
|
private static final String INTRO_MAGE =
|
||||||
"Being a magic user, I'm quite able to defend myself against local monsters, but I'm getting lost in no time, " +
|
"Oh, hello %s! I heard there was some ruckus regarding you and the mage's institute? " +
|
||||||
"it's very embarrassing. Probably you could help me? I would be happy to pay for your service with one of my best wands.";
|
"Oh never mind, I never liked those stick-in-the-muds anyway. If you're willing, I may have a task for you.\n\n";
|
||||||
|
|
||||||
private static final String TXT_BERRY2 =
|
private static final String INTRO_HUNTRESS =
|
||||||
"Any luck with a Rotberry seed, %s? No? Don't worry, I'm not in a hurry.";
|
"Oh, hello miss! A friendly face is a pleasant surprise down here isn't it? " +
|
||||||
|
"In fact, I swear I've seen your face before, but I can't put my finger on it... " +
|
||||||
private static final String TXT_DUST2 =
|
"Oh never mind, if you're here for adventure, I may have a task for you.\n\n";
|
||||||
|
|
||||||
|
private static final String INTRO_2 =
|
||||||
|
"I came here to find a rare ingredient to use in wandmaking, but I've gotten myself lost, " +
|
||||||
|
"and my magical shield is weakening. I'll need to leave soon, but can't bear to go without getting what I came for.\n\n";
|
||||||
|
|
||||||
|
|
||||||
|
private static final String INTRO_DUST =
|
||||||
|
"I'm looking for some corpse dust. It's a special kind of cursed bone meal that usually shows up in places like this. " +
|
||||||
|
"There should be a barricaded room around here somewhere, I'm sure some dust will turn up there. " +
|
||||||
|
"Do be careful though, the curse the dust carries is quite potent, get back to me as fast as you can and I'll cleanse it for you.\n\n";
|
||||||
|
|
||||||
|
private static final String INTRO_EMBER =
|
||||||
|
"I'm looking for some fresh embers from a newborn fire elemental. Elementals usually pop up when a summoning ritual isn't controlled, " +
|
||||||
|
"so just find some candles and a ritual site and I'm sure you can get one to pop up. " +
|
||||||
|
"You might want to keep some sort of freezing item handy though, elementals are very powerful, but ice will take them down quite easily.\n\n";
|
||||||
|
|
||||||
|
private static final String INTRO_BERRY =
|
||||||
|
"The old warden of this prison kept a rotberry plant, and I'm after one of its seeds. The plant has probably gone wild by now though, " +
|
||||||
|
"so getting it to give up a seed might be tricky. Its garden should be somewhere around here. " +
|
||||||
|
"Try to keep away from its vine lashers if you want to stay in one piece. Using fire might be tempting but please don't, you'll kill the plant and destroy its seeds.\n\n";
|
||||||
|
|
||||||
|
private static final String INTRO_4 =
|
||||||
|
"If you can get that for me, I'll be happy to pay you with one of my finely crafted wands! " +
|
||||||
|
"I brought two with me, so you can take whichever one you prefer.";
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
private static final String REMINDER_DUST =
|
||||||
"Any luck with corpse dust, %s? Bone piles are the most obvious places to look.";
|
"Any luck with corpse dust, %s? Bone piles are the most obvious places to look.";
|
||||||
|
|
||||||
|
private static final String REMINDER_EMBER =
|
||||||
|
"";
|
||||||
|
|
||||||
|
private static final String REMINDER_BERRY =
|
||||||
|
"Any luck with a Rotberry seed, %s? No? Don't worry, I'm not in a hurry.";
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean act() {
|
protected boolean act() {
|
||||||
|
@ -116,23 +153,64 @@ public class Wandmaker extends NPC {
|
||||||
sprite.turnTo( pos, Dungeon.hero.pos );
|
sprite.turnTo( pos, Dungeon.hero.pos );
|
||||||
if (Quest.given) {
|
if (Quest.given) {
|
||||||
|
|
||||||
Item item = Quest.alternative ?
|
Item item;
|
||||||
Dungeon.hero.belongings.getItem( CorpseDust.class ) :
|
switch (Quest.type) {
|
||||||
Dungeon.hero.belongings.getItem( Rotberry.Seed.class );
|
case 1:
|
||||||
|
default:
|
||||||
|
item = Dungeon.hero.belongings.getItem(CorpseDust.class);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
item = Dungeon.hero.belongings.getItem(CorpseDust.class); //TODO: elemental embers
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
item = Dungeon.hero.belongings.getItem(Rotberry.Seed.class);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
GameScene.show( new WndWandmaker( this, item ) );
|
GameScene.show( new WndWandmaker( this, item ) );
|
||||||
} else {
|
} else {
|
||||||
tell( Quest.alternative ? TXT_DUST2 : TXT_BERRY2, Dungeon.hero.givenName() );
|
tell( "not yet", Dungeon.hero.givenName() ); //TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Quest.placeItem();
|
|
||||||
|
|
||||||
if (Quest.given)
|
String msg = "";
|
||||||
tell(Quest.alternative ? TXT_DUST1 : TXT_BERRY1);
|
switch(Dungeon.hero.heroClass){
|
||||||
|
case WARRIOR:
|
||||||
|
msg += INTRO_WARRIOR;
|
||||||
|
break;
|
||||||
|
case ROGUE:
|
||||||
|
msg += INTRO_ROGUE;
|
||||||
|
break;
|
||||||
|
case MAGE:
|
||||||
|
msg += INTRO_MAGE;
|
||||||
|
break;
|
||||||
|
case HUNTRESS:
|
||||||
|
msg += INTRO_HUNTRESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg += INTRO_2;
|
||||||
|
|
||||||
|
switch (Quest.type){
|
||||||
|
case 1:
|
||||||
|
msg += INTRO_DUST;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
msg += INTRO_EMBER;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
msg += INTRO_BERRY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg += INTRO_4;
|
||||||
|
|
||||||
|
tell(msg, Dungeon.hero.givenName()); //TODO probable want to make this 2 separate windows
|
||||||
|
|
||||||
Journal.add( Journal.Feature.WANDMAKER );
|
Journal.add( Journal.Feature.WANDMAKER );
|
||||||
|
Quest.given = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,11 +226,14 @@ public class Wandmaker extends NPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Quest {
|
public static class Quest {
|
||||||
|
|
||||||
|
private static int type;
|
||||||
|
// 1 = corpse dust quest
|
||||||
|
// 2 = elemental embers quest
|
||||||
|
// 3 = rotberry quest
|
||||||
|
|
||||||
private static boolean spawned;
|
private static boolean spawned;
|
||||||
|
|
||||||
private static boolean alternative;
|
|
||||||
|
|
||||||
private static boolean given;
|
private static boolean given;
|
||||||
|
|
||||||
public static Wand wand1;
|
public static Wand wand1;
|
||||||
|
@ -160,6 +241,7 @@ public class Wandmaker extends NPC {
|
||||||
|
|
||||||
public static void reset() {
|
public static void reset() {
|
||||||
spawned = false;
|
spawned = false;
|
||||||
|
type = 0;
|
||||||
|
|
||||||
wand1 = null;
|
wand1 = null;
|
||||||
wand2 = null;
|
wand2 = null;
|
||||||
|
@ -168,10 +250,12 @@ public class Wandmaker extends NPC {
|
||||||
private static final String NODE = "wandmaker";
|
private static final String NODE = "wandmaker";
|
||||||
|
|
||||||
private static final String SPAWNED = "spawned";
|
private static final String SPAWNED = "spawned";
|
||||||
private static final String ALTERNATIVE = "alternative";
|
private static final String TYPE = "type";
|
||||||
private static final String GIVEN = "given";
|
private static final String GIVEN = "given";
|
||||||
private static final String WAND1 = "wand1";
|
private static final String WAND1 = "wand1";
|
||||||
private static final String WAND2 = "wand2";
|
private static final String WAND2 = "wand2";
|
||||||
|
|
||||||
|
private static final String RITUALPOS = "ritualpos";
|
||||||
|
|
||||||
public static void storeInBundle( Bundle bundle ) {
|
public static void storeInBundle( Bundle bundle ) {
|
||||||
|
|
||||||
|
@ -181,12 +265,17 @@ public class Wandmaker extends NPC {
|
||||||
|
|
||||||
if (spawned) {
|
if (spawned) {
|
||||||
|
|
||||||
node.put( ALTERNATIVE, alternative );
|
node.put( TYPE, type );
|
||||||
|
|
||||||
node.put(GIVEN, given );
|
node.put( GIVEN, given );
|
||||||
|
|
||||||
node.put( WAND1, wand1 );
|
node.put( WAND1, wand1 );
|
||||||
node.put( WAND2, wand2 );
|
node.put(WAND2, wand2);
|
||||||
|
|
||||||
|
if (type == 2){
|
||||||
|
node.put( RITUALPOS, CeremonialCandle.ritualPos );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle.put( NODE, node );
|
bundle.put( NODE, node );
|
||||||
|
@ -197,81 +286,89 @@ public class Wandmaker extends NPC {
|
||||||
Bundle node = bundle.getBundle( NODE );
|
Bundle node = bundle.getBundle( NODE );
|
||||||
|
|
||||||
if (!node.isNull() && (spawned = node.getBoolean( SPAWNED ))) {
|
if (!node.isNull() && (spawned = node.getBoolean( SPAWNED ))) {
|
||||||
|
|
||||||
alternative = node.getBoolean( ALTERNATIVE );
|
//TODO remove when pre-0.3.2 saves are no longer supported
|
||||||
|
if (bundle.contains(TYPE)) {
|
||||||
|
type = node.getInt(TYPE);
|
||||||
|
} else {
|
||||||
|
type = node.getBoolean("alternative")? 1 : 3;
|
||||||
|
}
|
||||||
|
|
||||||
given = node.getBoolean( GIVEN );
|
given = node.getBoolean( GIVEN );
|
||||||
|
|
||||||
wand1 = (Wand)node.get( WAND1 );
|
wand1 = (Wand)node.get( WAND1 );
|
||||||
wand2 = (Wand)node.get( WAND2 );
|
wand2 = (Wand)node.get( WAND2 );
|
||||||
|
|
||||||
|
if (type == 2){
|
||||||
|
CeremonialCandle.ritualPos = bundle.getInt( RITUALPOS );
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void spawn( PrisonLevel level, Room room ) {
|
public static boolean spawn( PrisonLevel level, Room room, Collection<Room> rooms ) {
|
||||||
if (!spawned && Dungeon.depth > 6 && Random.Int( 10 - Dungeon.depth ) == 0) {
|
if (!spawned && Dungeon.depth > 6 && Random.Int( 10 - Dungeon.depth ) == 0
|
||||||
|
|| type != 0) {
|
||||||
Wandmaker npc = new Wandmaker();
|
// decide between 1,2, or 3 for quest type.
|
||||||
do {
|
// but if the no herbalism challenge is enabled, only pick 1 or 2, no rotberry.
|
||||||
npc.pos = room.random();
|
if (type == 0) type = Random.Int(Dungeon.isChallenged(Challenges.NO_HERBALISM) ? 2 : 3)+1;
|
||||||
} while (level.map[npc.pos] == Terrain.ENTRANCE || level.map[npc.pos] == Terrain.SIGN);
|
|
||||||
level.mobs.add( npc );
|
|
||||||
|
|
||||||
spawned = true;
|
|
||||||
alternative = Random.Int( 2 ) == 0;
|
|
||||||
|
|
||||||
given = false;
|
|
||||||
wand1 = (Wand) Generator.random(Generator.Category.WAND);
|
|
||||||
wand1.upgrade();
|
|
||||||
|
|
||||||
do {
|
//note that we set the type but can fail here. This ensures that if a level needs to be re-generated
|
||||||
wand2 = (Wand) Generator.random(Generator.Category.WAND);
|
//we don't re-roll the quest, it will try to assign itself to that new level with the same type.
|
||||||
} while (wand2.getClass().equals(wand1.getClass()));
|
if (setRoom( rooms )){
|
||||||
wand2.upgrade();
|
Wandmaker npc = new Wandmaker();
|
||||||
|
do {
|
||||||
|
npc.pos = room.random();
|
||||||
|
} while (level.map[npc.pos] == Terrain.ENTRANCE || level.map[npc.pos] == Terrain.SIGN);
|
||||||
|
level.mobs.add( npc );
|
||||||
|
|
||||||
|
spawned = true;
|
||||||
|
|
||||||
|
given = false;
|
||||||
|
wand1 = (Wand) Generator.random(Generator.Category.WAND);
|
||||||
|
wand1.upgrade();
|
||||||
|
|
||||||
|
do {
|
||||||
|
wand2 = (Wand) Generator.random(Generator.Category.WAND);
|
||||||
|
} while (wand2.getClass().equals(wand1.getClass()));
|
||||||
|
wand2.upgrade();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void placeItem() {
|
private static boolean setRoom( Collection<Room> rooms) {
|
||||||
if (alternative) {
|
Room questRoom = null;
|
||||||
|
for (Room r : rooms){
|
||||||
ArrayList<Heap> candidates = new ArrayList<Heap>();
|
if (r.type == Room.Type.STANDARD && r.width() > 5 && r.height() > 5){
|
||||||
for (Heap heap : Dungeon.level.heaps.values()) {
|
if (type == 2 || r.connected.size() == 1){
|
||||||
if (heap.type == Heap.Type.SKELETON && !Dungeon.visible[heap.pos]) {
|
questRoom = r;
|
||||||
candidates.add( heap );
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candidates.size() > 0) {
|
|
||||||
Random.element( candidates ).drop( new CorpseDust() );
|
|
||||||
given = true;
|
|
||||||
} else {
|
|
||||||
int pos = Dungeon.level.randomRespawnCell();
|
|
||||||
while (Dungeon.level.heaps.get( pos ) != null) {
|
|
||||||
pos = Dungeon.level.randomRespawnCell();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos != -1) {
|
|
||||||
Heap heap = Dungeon.level.drop(new CorpseDust(), pos);
|
|
||||||
heap.type = Heap.Type.SKELETON;
|
|
||||||
heap.sprite.link();
|
|
||||||
given = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
int shrubPos = Dungeon.level.randomRespawnCell();
|
|
||||||
while (Dungeon.level.heaps.get( shrubPos ) != null) {
|
|
||||||
shrubPos = Dungeon.level.randomRespawnCell();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shrubPos != -1) {
|
|
||||||
Dungeon.level.plant(new Rotberry.Seed(), shrubPos);
|
|
||||||
given = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (questRoom == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type){
|
||||||
|
case 1: default:
|
||||||
|
questRoom.type = Room.Type.MASS_GRAVE;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
questRoom.type = Room.Type.RITUAL_SITE;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
questRoom.type = Room.Type.ROT_GARDEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void complete() {
|
public static void complete() {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.NewbornElemental;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,7 +87,10 @@ public class CeremonialCandle extends Item {
|
||||||
|
|
||||||
NewbornElemental elemental = new NewbornElemental();
|
NewbornElemental elemental = new NewbornElemental();
|
||||||
elemental.pos = ritualPos;
|
elemental.pos = ritualPos;
|
||||||
Dungeon.level.mobs.add( elemental );
|
elemental.state = elemental.HUNTING;
|
||||||
|
GameScene.add(elemental, 1);
|
||||||
|
|
||||||
|
//TODO visuals
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,14 +82,7 @@ public class PrisonLevel extends RegularLevel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return Wandmaker.Quest.spawn( this, roomEntrance, rooms );
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createItems() {
|
|
||||||
super.createItems();
|
|
||||||
|
|
||||||
Wandmaker.Quest.spawn( this, roomEntrance );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.painters;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.quest.CeremonialCandle;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||||
|
@ -45,6 +46,13 @@ public class RitualSitePainter extends Painter {
|
||||||
vis.pos(c.x - 1, c.y - 1);
|
vis.pos(c.x - 1, c.y - 1);
|
||||||
|
|
||||||
level.customTiles.add(vis);
|
level.customTiles.add(vis);
|
||||||
|
|
||||||
|
level.addItemToSpawn(new CeremonialCandle());
|
||||||
|
level.addItemToSpawn(new CeremonialCandle());
|
||||||
|
level.addItemToSpawn(new CeremonialCandle());
|
||||||
|
level.addItemToSpawn(new CeremonialCandle());
|
||||||
|
|
||||||
|
CeremonialCandle.ritualPos = c.x + (Level.WIDTH * c.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RitualMarker extends CustomTileVisual{
|
public static class RitualMarker extends CustomTileVisual{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user