V0.1.0 Partial Commit
changed package and application names to differentiate from main PD release
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.npcs;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.EquipableItem;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.quest.DarkGold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.quest.Pickaxe;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room.Type;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.BlacksmithSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBlacksmith;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Blacksmith extends Mob.NPC {
|
||||
|
||||
private static final String TXT_GOLD_1 =
|
||||
"Hey human! Wanna be useful, eh? Take dis pickaxe and mine me some _dark gold ore_, _15 pieces_ should be enough. " +
|
||||
"What do you mean, how am I gonna pay? You greedy...\n" +
|
||||
"Ok, ok, I don't have money to pay, but I can do some smithin' for you. Consider yourself lucky, " +
|
||||
"I'm the only blacksmith around.";
|
||||
private static final String TXT_BLOOD_1 =
|
||||
"Hey human! Wanna be useful, eh? Take dis pickaxe and _kill a bat_ wit' it, I need its blood on the head. " +
|
||||
"What do you mean, how am I gonna pay? You greedy...\n" +
|
||||
"Ok, ok, I don't have money to pay, but I can do some smithin' for you. Consider yourself lucky, " +
|
||||
"I'm the only blacksmith around.";
|
||||
private static final String TXT2 =
|
||||
"Are you kiddin' me? Where is my pickaxe?!";
|
||||
private static final String TXT3 =
|
||||
"Dark gold ore. 15 pieces. Seriously, is it dat hard?";
|
||||
private static final String TXT4 =
|
||||
"I said I need bat blood on the pickaxe. Chop chop!";
|
||||
private static final String TXT_COMPLETED =
|
||||
"Oh, you have returned... Better late dan never.";
|
||||
private static final String TXT_GET_LOST =
|
||||
"I'm busy. Get lost!";
|
||||
|
||||
private static final String TXT_LOOKS_BETTER = "your %s certainly looks better now";
|
||||
|
||||
{
|
||||
name = "troll blacksmith";
|
||||
spriteClass = BlacksmithSprite.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
throwItem();
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interact() {
|
||||
|
||||
sprite.turnTo( pos, Dungeon.hero.pos );
|
||||
|
||||
if (!Quest.given) {
|
||||
|
||||
GameScene.show( new WndQuest( this,
|
||||
Quest.alternative ? TXT_BLOOD_1 : TXT_GOLD_1 ) {
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
super.onBackPressed();
|
||||
|
||||
Quest.given = true;
|
||||
Quest.completed = false;
|
||||
|
||||
Pickaxe pick = new Pickaxe();
|
||||
if (pick.doPickUp( Dungeon.hero )) {
|
||||
GLog.i( Hero.TXT_YOU_NOW_HAVE, pick.name() );
|
||||
} else {
|
||||
Dungeon.level.drop( pick, Dungeon.hero.pos ).sprite.drop();
|
||||
}
|
||||
};
|
||||
} );
|
||||
|
||||
Journal.add( Journal.Feature.TROLL );
|
||||
|
||||
} else if (!Quest.completed) {
|
||||
if (Quest.alternative) {
|
||||
|
||||
Pickaxe pick = Dungeon.hero.belongings.getItem( Pickaxe.class );
|
||||
if (pick == null) {
|
||||
tell( TXT2 );
|
||||
} else if (!pick.bloodStained) {
|
||||
tell( TXT4 );
|
||||
} else {
|
||||
if (pick.isEquipped( Dungeon.hero )) {
|
||||
pick.doUnequip( Dungeon.hero, false );
|
||||
}
|
||||
pick.detach( Dungeon.hero.belongings.backpack );
|
||||
tell( TXT_COMPLETED );
|
||||
|
||||
Quest.completed = true;
|
||||
Quest.reforged = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Pickaxe pick = Dungeon.hero.belongings.getItem( Pickaxe.class );
|
||||
DarkGold gold = Dungeon.hero.belongings.getItem( DarkGold.class );
|
||||
if (pick == null) {
|
||||
tell( TXT2 );
|
||||
} else if (gold == null || gold.quantity() < 15) {
|
||||
tell( TXT3 );
|
||||
} else {
|
||||
if (pick.isEquipped( Dungeon.hero )) {
|
||||
pick.doUnequip( Dungeon.hero, false );
|
||||
}
|
||||
pick.detach( Dungeon.hero.belongings.backpack );
|
||||
gold.detachAll( Dungeon.hero.belongings.backpack );
|
||||
tell( TXT_COMPLETED );
|
||||
|
||||
Quest.completed = true;
|
||||
Quest.reforged = false;
|
||||
}
|
||||
|
||||
}
|
||||
} else if (!Quest.reforged) {
|
||||
|
||||
GameScene.show( new WndBlacksmith( this, Dungeon.hero ) );
|
||||
|
||||
} else {
|
||||
|
||||
tell( TXT_GET_LOST );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void tell( String text ) {
|
||||
GameScene.show( new WndQuest( this, text ) );
|
||||
}
|
||||
|
||||
public static String verify( Item item1, Item item2 ) {
|
||||
|
||||
if (item1 == item2) {
|
||||
return "Select 2 different items, not the same item twice!";
|
||||
}
|
||||
|
||||
if (!item1.isSimilar( item2 )) {
|
||||
return "Select 2 items of the same type!";
|
||||
}
|
||||
|
||||
if (!item1.isIdentified() || !item2.isIdentified()) {
|
||||
return "I need to know what I'm working with, identify them first!";
|
||||
}
|
||||
|
||||
if (item1.cursed || item2.cursed) {
|
||||
return "I don't work with cursed items!";
|
||||
}
|
||||
|
||||
if (item1.level < 0 || item2.level < 0) {
|
||||
return "It's a junk, the quality is too poor!";
|
||||
}
|
||||
|
||||
if (!item1.isUpgradable() || !item2.isUpgradable()) {
|
||||
return "I can't reforge these items!";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void upgrade( Item item1, Item item2 ) {
|
||||
|
||||
Item first, second;
|
||||
if (item2.level > item1.level) {
|
||||
first = item2;
|
||||
second = item1;
|
||||
} else {
|
||||
first = item1;
|
||||
second = item2;
|
||||
}
|
||||
|
||||
Sample.INSTANCE.play( Assets.SND_EVOKE );
|
||||
ScrollOfUpgrade.upgrade( Dungeon.hero );
|
||||
Item.evoke( Dungeon.hero );
|
||||
|
||||
if (first.isEquipped( Dungeon.hero )) {
|
||||
((EquipableItem)first).doUnequip( Dungeon.hero, true );
|
||||
}
|
||||
first.upgrade();
|
||||
GLog.p( TXT_LOOKS_BETTER, first.name() );
|
||||
Dungeon.hero.spendAndNext( 2f );
|
||||
Badges.validateItemLevelAquired( first );
|
||||
|
||||
if (second.isEquipped( Dungeon.hero )) {
|
||||
((EquipableItem)second).doUnequip( Dungeon.hero, false );
|
||||
}
|
||||
second.detachAll( Dungeon.hero.belongings.backpack );
|
||||
|
||||
Quest.reforged = true;
|
||||
|
||||
Journal.remove( Journal.Feature.TROLL );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseSkill( Char enemy ) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( Buff buff ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"This troll blacksmith looks like all trolls look: he is tall and lean, and his skin resembles stone " +
|
||||
"in both color and texture. The troll blacksmith is tinkering with unproportionally small tools.";
|
||||
}
|
||||
|
||||
public static class Quest {
|
||||
|
||||
private static boolean spawned;
|
||||
|
||||
private static boolean alternative;
|
||||
private static boolean given;
|
||||
private static boolean completed;
|
||||
private static boolean reforged;
|
||||
|
||||
public static void reset() {
|
||||
spawned = false;
|
||||
given = false;
|
||||
completed = false;
|
||||
reforged = false;
|
||||
}
|
||||
|
||||
private static final String NODE = "blacksmith";
|
||||
|
||||
private static final String SPAWNED = "spawned";
|
||||
private static final String ALTERNATIVE = "alternative";
|
||||
private static final String GIVEN = "given";
|
||||
private static final String COMPLETED = "completed";
|
||||
private static final String REFORGED = "reforged";
|
||||
|
||||
public static void storeInBundle( Bundle bundle ) {
|
||||
|
||||
Bundle node = new Bundle();
|
||||
|
||||
node.put( SPAWNED, spawned );
|
||||
|
||||
if (spawned) {
|
||||
node.put( ALTERNATIVE, alternative );
|
||||
node.put( GIVEN, given );
|
||||
node.put( COMPLETED, completed );
|
||||
node.put( REFORGED, reforged );
|
||||
}
|
||||
|
||||
bundle.put( NODE, node );
|
||||
}
|
||||
|
||||
public static void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
Bundle node = bundle.getBundle( NODE );
|
||||
|
||||
if (!node.isNull() && (spawned = node.getBoolean( SPAWNED ))) {
|
||||
alternative = node.getBoolean( ALTERNATIVE );
|
||||
given = node.getBoolean( GIVEN );
|
||||
completed = node.getBoolean( COMPLETED );
|
||||
reforged = node.getBoolean( REFORGED );
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static void spawn( Collection<Room> rooms ) {
|
||||
if (!spawned && Dungeon.depth > 11 && Random.Int( 15 - Dungeon.depth ) == 0) {
|
||||
|
||||
Room blacksmith = null;
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.STANDARD && r.width() > 4 && r.height() > 4) {
|
||||
blacksmith = r;
|
||||
blacksmith.type = Type.BLACKSMITH;
|
||||
|
||||
spawned = true;
|
||||
alternative = Random.Int( 2 ) == 0;
|
||||
|
||||
given = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.npcs;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
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.ParalyticGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.quest.DriedRose;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.quest.RatSkull;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.SewerLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.FetidRatSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.GhostSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndSadGhost;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Ghost extends Mob.NPC {
|
||||
|
||||
{
|
||||
name = "sad ghost";
|
||||
spriteClass = GhostSprite.class;
|
||||
|
||||
flying = true;
|
||||
|
||||
state = State.WANDERING;
|
||||
}
|
||||
|
||||
private static final String TXT_ROSE1 =
|
||||
"Hello adventurer... Once I was like you - strong and confident... " +
|
||||
"And now I'm dead... But I can't leave this place... Not until I have my _dried rose_... " +
|
||||
"It's very important to me... Some monster stole it from my body...";
|
||||
|
||||
private static final String TXT_ROSE2 =
|
||||
"Please... Help me... Find the rose...";
|
||||
|
||||
private static final String TXT_RAT1 =
|
||||
"Hello adventurer... Once I was like you - strong and confident... " +
|
||||
"And now I'm dead... But I can't leave this place... Not until I have my revenge... " +
|
||||
"Slay the _fetid rat_, that has taken my life...";
|
||||
|
||||
private static final String TXT_RAT2 =
|
||||
"Please... Help me... Slay the abomination...";
|
||||
|
||||
|
||||
public Ghost() {
|
||||
super();
|
||||
|
||||
Sample.INSTANCE.load( Assets.SND_GHOST );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseSkill( Char enemy ) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "evaded";
|
||||
}
|
||||
|
||||
@Override
|
||||
public float speed() {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Char chooseEnemy() {
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( Buff buff ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interact() {
|
||||
sprite.turnTo( pos, Dungeon.hero.pos );
|
||||
|
||||
Sample.INSTANCE.play( Assets.SND_GHOST );
|
||||
|
||||
if (Quest.given) {
|
||||
|
||||
Item item = Quest.alternative ?
|
||||
Dungeon.hero.belongings.getItem( RatSkull.class ) :
|
||||
Dungeon.hero.belongings.getItem( DriedRose.class );
|
||||
if (item != null) {
|
||||
GameScene.show( new WndSadGhost( this, item ) );
|
||||
} else {
|
||||
GameScene.show( new WndQuest( this, Quest.alternative ? TXT_RAT2 : TXT_ROSE2 ) );
|
||||
|
||||
int newPos = -1;
|
||||
for (int i=0; i < 10; i++) {
|
||||
newPos = Dungeon.level.randomRespawnCell();
|
||||
if (newPos != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newPos != -1) {
|
||||
|
||||
Actor.freeCell( pos );
|
||||
|
||||
CellEmitter.get( pos ).start( Speck.factory( Speck.LIGHT ), 0.2f, 3 );
|
||||
pos = newPos;
|
||||
sprite.place( pos );
|
||||
sprite.visible = Dungeon.visible[pos];
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
GameScene.show( new WndQuest( this, Quest.alternative ? TXT_RAT1 : TXT_ROSE1 ) );
|
||||
Quest.given = true;
|
||||
|
||||
Journal.add( Journal.Feature.GHOST );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"The ghost is barely visible. It looks like a shapeless " +
|
||||
"spot of faint light with a sorrowful face.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Paralysis.class );
|
||||
IMMUNITIES.add( Roots.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
|
||||
public static class Quest {
|
||||
|
||||
private static boolean spawned;
|
||||
|
||||
private static boolean alternative;
|
||||
|
||||
private static boolean given;
|
||||
|
||||
private static boolean processed;
|
||||
|
||||
private static int depth;
|
||||
|
||||
private static int left2kill;
|
||||
|
||||
public static Weapon weapon;
|
||||
public static Armor armor;
|
||||
|
||||
public static void reset() {
|
||||
spawned = false;
|
||||
|
||||
weapon = null;
|
||||
armor = null;
|
||||
}
|
||||
|
||||
private static final String NODE = "sadGhost";
|
||||
|
||||
private static final String SPAWNED = "spawned";
|
||||
private static final String ALTERNATIVE = "alternative";
|
||||
private static final String LEFT2KILL = "left2kill";
|
||||
private static final String GIVEN = "given";
|
||||
private static final String PROCESSED = "processed";
|
||||
private static final String DEPTH = "depth";
|
||||
private static final String WEAPON = "weapon";
|
||||
private static final String ARMOR = "armor";
|
||||
|
||||
public static void storeInBundle( Bundle bundle ) {
|
||||
|
||||
Bundle node = new Bundle();
|
||||
|
||||
node.put( SPAWNED, spawned );
|
||||
|
||||
if (spawned) {
|
||||
|
||||
node.put( ALTERNATIVE, alternative );
|
||||
if (!alternative) {
|
||||
node.put( LEFT2KILL, left2kill );
|
||||
}
|
||||
|
||||
node.put( GIVEN, given );
|
||||
node.put( DEPTH, depth );
|
||||
node.put( PROCESSED, processed );
|
||||
|
||||
node.put( WEAPON, weapon );
|
||||
node.put( ARMOR, armor );
|
||||
}
|
||||
|
||||
bundle.put( NODE, node );
|
||||
}
|
||||
|
||||
public static void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
Bundle node = bundle.getBundle( NODE );
|
||||
|
||||
if (!node.isNull() && (spawned = node.getBoolean( SPAWNED ))) {
|
||||
|
||||
alternative = node.getBoolean( ALTERNATIVE );
|
||||
if (!alternative) {
|
||||
left2kill = node.getInt( LEFT2KILL );
|
||||
}
|
||||
|
||||
given = node.getBoolean( GIVEN );
|
||||
depth = node.getInt( DEPTH );
|
||||
processed = node.getBoolean( PROCESSED );
|
||||
|
||||
weapon = (Weapon)node.get( WEAPON );
|
||||
armor = (Armor)node.get( ARMOR );
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static void spawn( SewerLevel level ) {
|
||||
if (!spawned && Dungeon.depth > 1 && Random.Int( 5 - Dungeon.depth ) == 0) {
|
||||
|
||||
Ghost ghost = new Ghost();
|
||||
do {
|
||||
ghost.pos = level.randomRespawnCell();
|
||||
} while (ghost.pos == -1);
|
||||
level.mobs.add( ghost );
|
||||
Actor.occupyCell( ghost );
|
||||
|
||||
spawned = true;
|
||||
alternative = Random.Int( 2 ) == 0;
|
||||
if (!alternative) {
|
||||
left2kill = 8;
|
||||
}
|
||||
|
||||
given = false;
|
||||
processed = false;
|
||||
depth = Dungeon.depth;
|
||||
|
||||
do {
|
||||
weapon = (Weapon)Generator.random( Generator.Category.WEAPON );
|
||||
} while (weapon instanceof MissileWeapon);
|
||||
armor = (Armor)Generator.random( Generator.Category.ARMOR );
|
||||
|
||||
for (int i=0; i < 3; i++) {
|
||||
Item another;
|
||||
do {
|
||||
another = Generator.random( Generator.Category.WEAPON );
|
||||
} while (another instanceof MissileWeapon);
|
||||
if (another.level > weapon.level) {
|
||||
weapon = (Weapon)another;
|
||||
}
|
||||
another = Generator.random( Generator.Category.ARMOR );
|
||||
if (another.level > armor.level) {
|
||||
armor = (Armor)another;
|
||||
}
|
||||
}
|
||||
weapon.identify();
|
||||
armor.identify();
|
||||
}
|
||||
}
|
||||
|
||||
public static void process( int pos ) {
|
||||
if (spawned && given && !processed && (depth == Dungeon.depth)) {
|
||||
if (alternative) {
|
||||
|
||||
FetidRat rat = new FetidRat();
|
||||
rat.state = Mob.State.WANDERING;
|
||||
rat.pos = Dungeon.level.randomRespawnCell();
|
||||
if (rat.pos != -1) {
|
||||
GameScene.add( rat );
|
||||
processed = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (Random.Int( left2kill ) == 0) {
|
||||
Dungeon.level.drop( new DriedRose(), pos ).sprite.drop();
|
||||
processed = true;
|
||||
} else {
|
||||
left2kill--;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void complete() {
|
||||
weapon = null;
|
||||
armor = null;
|
||||
|
||||
Journal.remove( Journal.Feature.GHOST );
|
||||
}
|
||||
}
|
||||
|
||||
public static class FetidRat extends Mob {
|
||||
|
||||
{
|
||||
name = "fetid rat";
|
||||
spriteClass = FetidRatSprite.class;
|
||||
|
||||
HP = HT = 15;
|
||||
defenseSkill = 5;
|
||||
|
||||
EXP = 0;
|
||||
maxLvl = 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 2, 6 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseProc( Char enemy, int damage ) {
|
||||
|
||||
GameScene.add( Blob.seed( pos, 20, ParalyticGas.class ) );
|
||||
|
||||
return super.defenseProc(enemy, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
|
||||
Dungeon.level.drop( new RatSkull(), pos ).sprite.drop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"This marsupial rat is much larger, than a regular one. It is surrounded by a foul cloud.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Paralysis.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.npcs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Golem;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Monk;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.quest.DwarfToken;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.CityLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ImpSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndImp;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Imp extends Mob.NPC {
|
||||
|
||||
{
|
||||
name = "ambitious imp";
|
||||
spriteClass = ImpSprite.class;
|
||||
}
|
||||
|
||||
private static final String TXT_GOLEMS1 =
|
||||
"Are you an adventurer? I love adventurers! You can always rely on them " +
|
||||
"if something needs to be killed. Am I right? For bounty of course ;)\n" +
|
||||
"In my case this is _golems_ who need to be killed. You see, I'm going to start a " +
|
||||
"little business here, but these stupid golems are bad for business! " +
|
||||
"It's very hard to negotiate with wandering lumps of granite, damn them! " +
|
||||
"So please, kill... let's say _6 of them_ and a reward is yours.";
|
||||
|
||||
private static final String TXT_MONKS1 =
|
||||
"Are you an adventurer? I love adventurers! You can always rely on them " +
|
||||
"if something needs to be killed. Am I right? For bounty of course ;)\n" +
|
||||
"In my case this is _monks_ who need to be killed. You see, I'm going to start a " +
|
||||
"little business here, but these lunatics don't buy anything themselves and " +
|
||||
"will scare away other customers. " +
|
||||
"So please, kill... let's say _8 of them_ and a reward is yours.";
|
||||
|
||||
private static final String TXT_GOLEMS2 =
|
||||
"How is your golem safari going?";
|
||||
|
||||
private static final String TXT_MONKS2 =
|
||||
"Oh, you are still alive! I knew that your kung-fu is stronger ;) " +
|
||||
"Just don't forget to grab these monks' tokens.";
|
||||
|
||||
private static final String TXT_CYA = "See you, %s!";
|
||||
private static final String TXT_HEY = "Psst, %s!";
|
||||
|
||||
private boolean seenBefore = false;
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
|
||||
if (!Quest.given && Dungeon.visible[pos]) {
|
||||
if (!seenBefore) {
|
||||
yell( Utils.format( TXT_HEY, Dungeon.hero.className() ) );
|
||||
}
|
||||
seenBefore = true;
|
||||
} else {
|
||||
seenBefore = false;
|
||||
}
|
||||
|
||||
throwItem();
|
||||
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseSkill( Char enemy ) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "evaded";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( Buff buff ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interact() {
|
||||
|
||||
sprite.turnTo( pos, Dungeon.hero.pos );
|
||||
if (Quest.given) {
|
||||
|
||||
DwarfToken tokens = Dungeon.hero.belongings.getItem( DwarfToken.class );
|
||||
if (tokens != null && (tokens.quantity() >= 8 || (!Quest.alternative && tokens.quantity() >= 6))) {
|
||||
GameScene.show( new WndImp( this, tokens ) );
|
||||
} else {
|
||||
tell( Quest.alternative ? TXT_MONKS2 : TXT_GOLEMS2, Dungeon.hero.className() );
|
||||
}
|
||||
|
||||
} else {
|
||||
tell( Quest.alternative ? TXT_MONKS1 : TXT_GOLEMS1 );
|
||||
Quest.given = true;
|
||||
Quest.completed = false;
|
||||
|
||||
Journal.add( Journal.Feature.IMP );
|
||||
}
|
||||
}
|
||||
|
||||
private void tell( String format, Object...args ) {
|
||||
GameScene.show(
|
||||
new WndQuest( this, Utils.format( format, args ) ) );
|
||||
}
|
||||
|
||||
public void flee() {
|
||||
|
||||
yell( Utils.format( TXT_CYA, Dungeon.hero.className() ) );
|
||||
|
||||
destroy();
|
||||
sprite.die();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Imps are lesser demons. They are notable for neither their strength nor their magic talent, " +
|
||||
"but they are quite smart and sociable. Many imps prefer to live among non-demons.";
|
||||
}
|
||||
|
||||
public static class Quest {
|
||||
|
||||
private static boolean alternative;
|
||||
|
||||
private static boolean spawned;
|
||||
private static boolean given;
|
||||
private static boolean completed;
|
||||
|
||||
public static Ring reward;
|
||||
|
||||
public static void reset() {
|
||||
spawned = false;
|
||||
|
||||
reward = null;
|
||||
}
|
||||
|
||||
private static final String NODE = "demon";
|
||||
|
||||
private static final String ALTERNATIVE = "alternative";
|
||||
private static final String SPAWNED = "spawned";
|
||||
private static final String GIVEN = "given";
|
||||
private static final String COMPLETED = "completed";
|
||||
private static final String REWARD = "reward";
|
||||
|
||||
public static void storeInBundle( Bundle bundle ) {
|
||||
|
||||
Bundle node = new Bundle();
|
||||
|
||||
node.put( SPAWNED, spawned );
|
||||
|
||||
if (spawned) {
|
||||
node.put( ALTERNATIVE, alternative );
|
||||
|
||||
node.put( GIVEN, given );
|
||||
node.put( COMPLETED, completed );
|
||||
node.put( REWARD, reward );
|
||||
}
|
||||
|
||||
bundle.put( NODE, node );
|
||||
}
|
||||
|
||||
public static void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
Bundle node = bundle.getBundle( NODE );
|
||||
|
||||
if (!node.isNull() && (spawned = node.getBoolean( SPAWNED ))) {
|
||||
alternative = node.getBoolean( ALTERNATIVE );
|
||||
|
||||
given = node.getBoolean( GIVEN );
|
||||
completed = node.getBoolean( COMPLETED );
|
||||
reward = (Ring)node.get( REWARD );
|
||||
}
|
||||
}
|
||||
|
||||
public static void spawn( CityLevel level, Room room ) {
|
||||
if (!spawned && Dungeon.depth > 16 && Random.Int( 20 - Dungeon.depth ) == 0) {
|
||||
|
||||
Imp npc = new Imp();
|
||||
do {
|
||||
npc.pos = level.randomRespawnCell();
|
||||
} while (npc.pos == -1 || level.heaps.get( npc.pos ) != null);
|
||||
level.mobs.add( npc );
|
||||
Actor.occupyCell( npc );
|
||||
|
||||
spawned = true;
|
||||
alternative = Random.Int( 2 ) == 0;
|
||||
|
||||
given = false;
|
||||
|
||||
do {
|
||||
reward = (Ring)Generator.random( Generator.Category.RING );
|
||||
} while (reward.cursed);
|
||||
reward.upgrade( 2 );
|
||||
reward.cursed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void process( Mob mob ) {
|
||||
if (spawned && given && !completed) {
|
||||
if ((alternative && mob instanceof Monk) ||
|
||||
(!alternative && mob instanceof Golem)) {
|
||||
|
||||
Dungeon.level.drop( new DwarfToken(), mob.pos ).sprite.drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void complete() {
|
||||
reward = null;
|
||||
completed = true;
|
||||
|
||||
Journal.remove( Journal.Feature.IMP );
|
||||
}
|
||||
|
||||
public static boolean isCompleted() {
|
||||
return completed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.npcs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ImpSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
|
||||
public class ImpShopkeeper extends Shopkeeper {
|
||||
|
||||
private static final String TXT_GREETINGS = "Hello, friend!";
|
||||
|
||||
{
|
||||
name = "ambitious imp";
|
||||
spriteClass = ImpSprite.class;
|
||||
}
|
||||
|
||||
private boolean seenBefore = false;
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
|
||||
if (!seenBefore && Dungeon.visible[pos]) {
|
||||
yell( Utils.format( TXT_GREETINGS ) );
|
||||
seenBefore = true;
|
||||
}
|
||||
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void flee() {
|
||||
for (Heap heap: Dungeon.level.heaps.values()) {
|
||||
if (heap.type == Heap.Type.FOR_SALE) {
|
||||
CellEmitter.get( heap.pos ).burst( ElmoParticle.FACTORY, 4 );
|
||||
heap.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
destroy();
|
||||
|
||||
sprite.emitter().burst( Speck.factory( Speck.WOOL ), 15 );
|
||||
sprite.killAndErase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Imps are lesser demons. They are notable for neither their strength nor their magic talent. " +
|
||||
"But they are quite smart and sociable, and many of imps prefer to live and do business among non-demons.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.npcs;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.MirrorSprite;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class MirrorImage extends Mob.NPC {
|
||||
|
||||
{
|
||||
name = "mirror image";
|
||||
spriteClass = MirrorSprite.class;
|
||||
|
||||
state = State.HUNTING;
|
||||
|
||||
enemy = DUMMY;
|
||||
}
|
||||
|
||||
public int tier;
|
||||
|
||||
private int attack;
|
||||
private int damage;
|
||||
|
||||
private static final String TIER = "tier";
|
||||
private static final String ATTACK = "attack";
|
||||
private static final String DAMAGE = "damage";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( TIER, tier );
|
||||
bundle.put( ATTACK, attack );
|
||||
bundle.put( DAMAGE, damage );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
tier = bundle.getInt( TIER );
|
||||
attack = bundle.getInt( ATTACK );
|
||||
damage = bundle.getInt( DAMAGE );
|
||||
}
|
||||
|
||||
public void duplicate( Hero hero ) {
|
||||
tier = hero.tier();
|
||||
attack = hero.attackSkill( hero );
|
||||
damage = hero.damageRoll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return attack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
int dmg = super.attackProc( enemy, damage );
|
||||
|
||||
destroy();
|
||||
sprite.die();
|
||||
|
||||
return dmg;
|
||||
}
|
||||
|
||||
protected Char chooseEnemy() {
|
||||
|
||||
if (enemy == DUMMY || !enemy.isAlive()) {
|
||||
HashSet<Mob> enemies = new HashSet<Mob>();
|
||||
for (Mob mob:Dungeon.level.mobs) {
|
||||
if (mob.hostile && Level.fieldOfView[mob.pos]) {
|
||||
enemies.add( mob );
|
||||
}
|
||||
}
|
||||
|
||||
enemy = enemies.size() > 0 ? Random.element( enemies ) : DUMMY;
|
||||
}
|
||||
|
||||
return enemy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"This illusion bears a close resemblance to you, " +
|
||||
"but it's paler and twitches a little.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSprite sprite() {
|
||||
CharSprite s = super.sprite();
|
||||
((MirrorSprite)s).updateArmor( tier );
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interact() {
|
||||
|
||||
int curPos = pos;
|
||||
|
||||
moveSprite( pos, Dungeon.hero.pos );
|
||||
move( Dungeon.hero.pos );
|
||||
|
||||
Dungeon.hero.sprite.move( Dungeon.hero.pos, curPos );
|
||||
Dungeon.hero.move( curPos );
|
||||
|
||||
Dungeon.hero.spend( 1 / Dungeon.hero.speed() );
|
||||
Dungeon.hero.busy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.npcs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.RatKingSprite;
|
||||
|
||||
public class RatKing extends Mob.NPC {
|
||||
|
||||
{
|
||||
name = "rat king";
|
||||
spriteClass = RatKingSprite.class;
|
||||
|
||||
state = State.SLEEPING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseSkill( Char enemy ) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float speed() {
|
||||
return 2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Char chooseEnemy() {
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( Buff buff ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interact() {
|
||||
sprite.turnTo( pos, Dungeon.hero.pos );
|
||||
if (state == State.SLEEPING) {
|
||||
notice();
|
||||
yell( "I'm not sleeping!" );
|
||||
state = State.WANDERING;
|
||||
} else {
|
||||
yell( "What is it? I have no time for this nonsense. My kingdom won't rule itself!" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"This rat is a little bigger than a regular marsupial rat " +
|
||||
"and it's wearing a tiny crown on its head.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.npcs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ShopkeeperSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTradeItem;
|
||||
|
||||
public class Shopkeeper extends Mob.NPC {
|
||||
|
||||
{
|
||||
name = "shopkeeper";
|
||||
spriteClass = ShopkeeperSprite.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
|
||||
throwItem();
|
||||
|
||||
sprite.turnTo( pos, Dungeon.hero.pos );
|
||||
spend( TICK );
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
flee();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( Buff buff ) {
|
||||
flee();
|
||||
}
|
||||
|
||||
protected void flee() {
|
||||
for (Heap heap: Dungeon.level.heaps.values()) {
|
||||
if (heap.type == Heap.Type.FOR_SALE) {
|
||||
CellEmitter.get( heap.pos ).burst( ElmoParticle.FACTORY, 4 );
|
||||
heap.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
destroy();
|
||||
|
||||
sprite.killAndErase();
|
||||
CellEmitter.get( pos ).burst( ElmoParticle.FACTORY, 6 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"This stout guy looks more appropriate for a trade district in some large city " +
|
||||
"than for a dungeon. His prices explain why he prefers to do business here.";
|
||||
}
|
||||
|
||||
public static WndBag sell() {
|
||||
return GameScene.selectItem( itemSelector, WndBag.Mode.FOR_SALE, "Select an item to sell" );
|
||||
}
|
||||
|
||||
private static WndBag.Listener itemSelector = new WndBag.Listener() {
|
||||
@Override
|
||||
public void onSelect( Item item ) {
|
||||
if (item != null) {
|
||||
WndBag parentWnd = sell();
|
||||
GameScene.show( new WndTradeItem( item, parentWnd ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void interact() {
|
||||
sell();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.npcs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
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.ToxicGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.quest.CorpseDust;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfAmok;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfAvalanche;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfDisintegration;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFirebolt;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLightning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfPoison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfSlowness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfTelekinesis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.PrisonLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.plants.Plant;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.WandmakerSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndWandmaker;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Wandmaker extends Mob.NPC {
|
||||
|
||||
{
|
||||
name = "old wandmaker";
|
||||
spriteClass = WandmakerSprite.class;
|
||||
}
|
||||
|
||||
private static final String TXT_BERRY1 =
|
||||
"Oh, what a pleasant surprise to meet a decent person in such place! I came here for a rare ingredient - " +
|
||||
"a _Rotberry seed_. Being a magic user, I'm quite able to defend myself against local monsters, " +
|
||||
"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 TXT_DUST1 =
|
||||
"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. " +
|
||||
"Being a magic user, I'm quite able to defend myself against local monsters, 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 TXT_BERRY2 =
|
||||
"Any luck with a Rotberry seed, %s? No? Don't worry, I'm not in a hurry.";
|
||||
|
||||
private static final String TXT_DUST2 =
|
||||
"Any luck with corpse dust, %s? Bone piles are the most obvious places to look.";
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
throwItem();
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseSkill( Char enemy ) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "absorbed";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( Buff buff ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interact() {
|
||||
|
||||
sprite.turnTo( pos, Dungeon.hero.pos );
|
||||
if (Quest.given) {
|
||||
|
||||
Item item = Quest.alternative ?
|
||||
Dungeon.hero.belongings.getItem( CorpseDust.class ) :
|
||||
Dungeon.hero.belongings.getItem( Rotberry.Seed.class );
|
||||
if (item != null) {
|
||||
GameScene.show( new WndWandmaker( this, item ) );
|
||||
} else {
|
||||
tell( Quest.alternative ? TXT_DUST2 : TXT_BERRY2, Dungeon.hero.className() );
|
||||
}
|
||||
|
||||
} else {
|
||||
tell( Quest.alternative ? TXT_DUST1 : TXT_BERRY1 );
|
||||
Quest.given = true;
|
||||
|
||||
Quest.placeItem();
|
||||
|
||||
Journal.add( Journal.Feature.WANDMAKER );
|
||||
}
|
||||
}
|
||||
|
||||
private void tell( String format, Object...args ) {
|
||||
GameScene.show( new WndQuest( this, Utils.format( format, args ) ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"This old but hale gentleman wears a slightly confused " +
|
||||
"expression. He is protected by a magic shield.";
|
||||
}
|
||||
|
||||
public static class Quest {
|
||||
|
||||
private static boolean spawned;
|
||||
|
||||
private static boolean alternative;
|
||||
|
||||
private static boolean given;
|
||||
|
||||
public static Wand wand1;
|
||||
public static Wand wand2;
|
||||
|
||||
public static void reset() {
|
||||
spawned = false;
|
||||
|
||||
wand1 = null;
|
||||
wand2 = null;
|
||||
}
|
||||
|
||||
private static final String NODE = "wandmaker";
|
||||
|
||||
private static final String SPAWNED = "spawned";
|
||||
private static final String ALTERNATIVE = "alternative";
|
||||
private static final String GIVEN = "given";
|
||||
private static final String WAND1 = "wand1";
|
||||
private static final String WAND2 = "wand2";
|
||||
|
||||
public static void storeInBundle( Bundle bundle ) {
|
||||
|
||||
Bundle node = new Bundle();
|
||||
|
||||
node.put( SPAWNED, spawned );
|
||||
|
||||
if (spawned) {
|
||||
|
||||
node.put( ALTERNATIVE, alternative );
|
||||
|
||||
node.put(GIVEN, given );
|
||||
|
||||
node.put( WAND1, wand1 );
|
||||
node.put( WAND2, wand2 );
|
||||
}
|
||||
|
||||
bundle.put( NODE, node );
|
||||
}
|
||||
|
||||
public static void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
Bundle node = bundle.getBundle( NODE );
|
||||
|
||||
if (!node.isNull() && (spawned = node.getBoolean( SPAWNED ))) {
|
||||
|
||||
alternative = node.getBoolean( ALTERNATIVE );
|
||||
|
||||
given = node.getBoolean( GIVEN );
|
||||
|
||||
wand1 = (Wand)node.get( WAND1 );
|
||||
wand2 = (Wand)node.get( WAND2 );
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static void spawn( PrisonLevel level, Room room ) {
|
||||
if (!spawned && Dungeon.depth > 6 && Random.Int( 10 - Dungeon.depth ) == 0) {
|
||||
|
||||
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 );
|
||||
Actor.occupyCell( npc );
|
||||
|
||||
spawned = true;
|
||||
alternative = Random.Int( 2 ) == 0;
|
||||
|
||||
given = false;
|
||||
|
||||
switch (Random.Int( 5 )) {
|
||||
case 0:
|
||||
wand1 = new WandOfAvalanche();
|
||||
break;
|
||||
case 1:
|
||||
wand1 = new WandOfDisintegration();
|
||||
break;
|
||||
case 2:
|
||||
wand1 = new WandOfFirebolt();
|
||||
break;
|
||||
case 3:
|
||||
wand1 = new WandOfLightning();
|
||||
break;
|
||||
case 4:
|
||||
wand1 = new WandOfPoison();
|
||||
break;
|
||||
}
|
||||
wand1.random().upgrade();
|
||||
|
||||
switch (Random.Int( 5 )) {
|
||||
case 0:
|
||||
wand2 = new WandOfAmok();
|
||||
break;
|
||||
case 1:
|
||||
wand2 = new WandOfBlink();
|
||||
break;
|
||||
case 2:
|
||||
wand2 = new WandOfRegrowth();
|
||||
break;
|
||||
case 3:
|
||||
wand2 = new WandOfSlowness();
|
||||
break;
|
||||
case 4:
|
||||
wand2 = new WandOfTelekinesis();
|
||||
break;
|
||||
}
|
||||
wand2.random().upgrade();
|
||||
}
|
||||
}
|
||||
|
||||
public static void placeItem() {
|
||||
if (alternative) {
|
||||
|
||||
ArrayList<Heap> candidates = new ArrayList<Heap>();
|
||||
for (Heap heap : Dungeon.level.heaps.values()) {
|
||||
if (heap.type == Heap.Type.SKELETON && !Dungeon.visible[heap.pos]) {
|
||||
candidates.add( heap );
|
||||
}
|
||||
}
|
||||
|
||||
if (candidates.size() > 0) {
|
||||
Random.element( candidates ).drop( new CorpseDust() );
|
||||
} else {
|
||||
int pos = Dungeon.level.randomRespawnCell();
|
||||
while (Dungeon.level.heaps.get( pos ) != null) {
|
||||
pos = Dungeon.level.randomRespawnCell();
|
||||
}
|
||||
|
||||
Heap heap = Dungeon.level.drop( new CorpseDust(), pos );
|
||||
heap.type = Heap.Type.SKELETON;
|
||||
heap.sprite.link();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
int shrubPos = Dungeon.level.randomRespawnCell();
|
||||
while (Dungeon.level.heaps.get( shrubPos ) != null) {
|
||||
shrubPos = Dungeon.level.randomRespawnCell();
|
||||
}
|
||||
Dungeon.level.plant( new Rotberry.Seed(), shrubPos );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void complete() {
|
||||
wand1 = null;
|
||||
wand2 = null;
|
||||
|
||||
Journal.remove( Journal.Feature.WANDMAKER );
|
||||
}
|
||||
}
|
||||
|
||||
public static class Rotberry extends Plant {
|
||||
|
||||
private static final String TXT_DESC =
|
||||
"Berries of this shrub taste like sweet, sweet death.";
|
||||
|
||||
{
|
||||
image = 7;
|
||||
plantName = "Rotberry";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate( Char ch ) {
|
||||
super.activate( ch );
|
||||
|
||||
GameScene.add( Blob.seed( pos, 100, ToxicGas.class ) );
|
||||
|
||||
Dungeon.level.drop( new Seed(), pos ).sprite.drop();
|
||||
|
||||
if (ch != null) {
|
||||
Buff.prolong( ch, Roots.class, TICK * 3 );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String desc() {
|
||||
return TXT_DESC;
|
||||
}
|
||||
|
||||
public static class Seed extends Plant.Seed {
|
||||
{
|
||||
plantName = "Rotberry";
|
||||
|
||||
name = "seed of " + plantName;
|
||||
image = ItemSpriteSheet.SEED_ROTBERRY;
|
||||
|
||||
plantClass = Rotberry.class;
|
||||
alchemyClass = PotionOfStrength.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collect( Bag container ) {
|
||||
if (super.collect( container )) {
|
||||
|
||||
if (Dungeon.level != null) {
|
||||
for (Mob mob : Dungeon.level.mobs) {
|
||||
mob.beckon( Dungeon.hero.pos );
|
||||
}
|
||||
|
||||
GLog.w( "The seed emits a roar that echoes throughout the dungeon!" );
|
||||
CellEmitter.center( Dungeon.hero.pos ).start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
|
||||
Sample.INSTANCE.play( Assets.SND_CHALLENGE );
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String desc() {
|
||||
return TXT_DESC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user