V0.1.0 Partial Commit
changed package and application names to differentiate from main PD release
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class Assets {
|
||||
|
||||
public static final String ARCS_BG = "arcs1.png";
|
||||
public static final String ARCS_FG = "arcs2.png";
|
||||
public static final String DASHBOARD = "dashboard.png";
|
||||
|
||||
public static final String BANNERS = "banners.png";
|
||||
public static final String BADGES = "badges.png";
|
||||
public static final String AMULET = "amulet.png";
|
||||
|
||||
public static final String CHROME = "chrome.png";
|
||||
public static final String ICONS = "icons.png";
|
||||
public static final String STATUS = "status_pane.png";
|
||||
public static final String HP_BAR = "hp_bar.png";
|
||||
public static final String XP_BAR = "exp_bar.png";
|
||||
public static final String TOOLBAR = "toolbar.png";
|
||||
|
||||
public static final String WARRIOR = "warrior.png";
|
||||
public static final String MAGE = "mage.png";
|
||||
public static final String ROGUE = "rogue.png";
|
||||
public static final String HUNTRESS = "ranger.png";
|
||||
public static final String AVATARS = "avatars.png";
|
||||
|
||||
public static final String SURFACE = "surface.png";
|
||||
|
||||
public static final String FIREBALL = "fireball.png";
|
||||
public static final String SPECKS = "specks.png";
|
||||
public static final String EFFECTS = "effects.png";
|
||||
|
||||
public static final String RAT = "rat.png";
|
||||
public static final String GNOLL = "gnoll.png";
|
||||
public static final String CRAB = "crab.png";
|
||||
public static final String GOO = "goo.png";
|
||||
public static final String SWARM = "swarm.png";
|
||||
public static final String SKELETON = "skeleton.png";
|
||||
public static final String SHAMAN = "shaman.png";
|
||||
public static final String THIEF = "thief.png";
|
||||
public static final String TENGU = "tengu.png";
|
||||
public static final String SHEEP = "sheep.png";
|
||||
public static final String KEEPER = "shopkeeper.png";
|
||||
public static final String BAT = "bat.png";
|
||||
public static final String BRUTE = "brute.png";
|
||||
public static final String SPINNER = "spinner.png";
|
||||
public static final String DM300 = "dm300.png";
|
||||
public static final String WRAITH = "wraith.png";
|
||||
public static final String ELEMENTAL= "elemental.png";
|
||||
public static final String MONK = "monk.png";
|
||||
public static final String WARLOCK = "warlock.png";
|
||||
public static final String GOLEM = "golem.png";
|
||||
public static final String UNDEAD = "undead.png";
|
||||
public static final String KING = "king.png";
|
||||
public static final String STATUE = "statue.png";
|
||||
public static final String PIRANHA = "piranha.png";
|
||||
public static final String EYE = "eye.png";
|
||||
public static final String SUCCUBUS = "succubus.png";
|
||||
public static final String SCORPIO = "scorpio.png";
|
||||
public static final String ROTTING = "rotting_fist.png";
|
||||
public static final String BURNING = "burning_fist.png";
|
||||
public static final String YOG = "yog.png";
|
||||
public static final String LARVA = "larva.png";
|
||||
public static final String GHOST = "ghost.png";
|
||||
public static final String MAKER = "wandmaker.png";
|
||||
public static final String TROLL = "blacksmith.png";
|
||||
public static final String IMP = "demon.png";
|
||||
public static final String RATKING = "ratking.png";
|
||||
|
||||
public static final String ITEMS = "items.png";
|
||||
public static final String PLANTS = "plants.png";
|
||||
|
||||
public static final String TILES_SEWERS = "tiles0.png";
|
||||
public static final String TILES_PRISON = "tiles1.png";
|
||||
public static final String TILES_CAVES = "tiles2.png";
|
||||
public static final String TILES_CITY = "tiles3.png";
|
||||
public static final String TILES_HALLS = "tiles4.png";
|
||||
|
||||
public static final String WATER_SEWERS = "water0.png";
|
||||
public static final String WATER_PRISON = "water1.png";
|
||||
public static final String WATER_CAVES = "water2.png";
|
||||
public static final String WATER_CITY = "water3.png";
|
||||
public static final String WATER_HALLS = "water4.png";
|
||||
|
||||
public static final String BUFFS_SMALL = "buffs.png";
|
||||
public static final String BUFFS_LARGE = "large_buffs.png";
|
||||
public static final String SPELL_ICONS = "spell_icons.png";
|
||||
|
||||
public static final String FONTS1X = "font1x.png";
|
||||
public static final String FONTS15X = "font15x.png";
|
||||
public static final String FONTS2X = "font2x.png";
|
||||
public static final String FONTS25X = "font25x.png";
|
||||
public static final String FONTS3X = "font3x.png";
|
||||
|
||||
public static final String THEME = "theme.mp3";
|
||||
public static final String TUNE = "game.mp3";
|
||||
public static final String HAPPY = "surface.mp3";
|
||||
|
||||
public static final String SND_CLICK = "snd_click.mp3";
|
||||
public static final String SND_BADGE = "snd_badge.mp3";
|
||||
public static final String SND_GOLD = "snd_gold.mp3";
|
||||
|
||||
public static final String SND_OPEN = "snd_door_open.mp3";
|
||||
public static final String SND_UNLOCK = "snd_unlock.mp3";
|
||||
public static final String SND_ITEM = "snd_item.mp3";
|
||||
public static final String SND_DEWDROP = "snd_dewdrop.mp3";
|
||||
public static final String SND_HIT = "snd_hit.mp3";
|
||||
public static final String SND_MISS = "snd_miss.mp3";
|
||||
public static final String SND_STEP = "snd_step.mp3";
|
||||
public static final String SND_WATER = "snd_water.mp3";
|
||||
public static final String SND_DESCEND = "snd_descend.mp3";
|
||||
public static final String SND_EAT = "snd_eat.mp3";
|
||||
public static final String SND_READ = "snd_read.mp3";
|
||||
public static final String SND_LULLABY = "snd_lullaby.mp3";
|
||||
public static final String SND_DRINK = "snd_drink.mp3";
|
||||
public static final String SND_SHATTER = "snd_shatter.mp3";
|
||||
public static final String SND_ZAP = "snd_zap.mp3";
|
||||
public static final String SND_LIGHTNING= "snd_lightning.mp3";
|
||||
public static final String SND_LEVELUP = "snd_levelup.mp3";
|
||||
public static final String SND_DEATH = "snd_death.mp3";
|
||||
public static final String SND_CHALLENGE= "snd_challenge.mp3";
|
||||
public static final String SND_CURSED = "snd_cursed.mp3";
|
||||
public static final String SND_TRAP = "snd_trap.mp3";
|
||||
public static final String SND_EVOKE = "snd_evoke.mp3";
|
||||
public static final String SND_TOMB = "snd_tomb.mp3";
|
||||
public static final String SND_ALERT = "snd_alert.mp3";
|
||||
public static final String SND_MELD = "snd_meld.mp3";
|
||||
public static final String SND_BOSS = "snd_boss.mp3";
|
||||
public static final String SND_BLAST = "snd_blast.mp3";
|
||||
public static final String SND_PLANT = "snd_plant.mp3";
|
||||
public static final String SND_RAY = "snd_ray.mp3";
|
||||
public static final String SND_BEACON = "snd_beacon.mp3";
|
||||
public static final String SND_TELEPORT = "snd_teleport.mp3";
|
||||
public static final String SND_CHARMS = "snd_charms.mp3";
|
||||
public static final String SND_MASTERY = "snd_mastery.mp3";
|
||||
public static final String SND_PUFF = "snd_puff.mp3";
|
||||
public static final String SND_ROCKS = "snd_rocks.mp3";
|
||||
public static final String SND_BURNING = "snd_burning.mp3";
|
||||
public static final String SND_FALLING = "snd_falling.mp3";
|
||||
public static final String SND_GHOST = "snd_ghost.mp3";
|
||||
public static final String SND_SECRET = "snd_secret.mp3";
|
||||
public static final String SND_BONES = "snd_bones.mp3";
|
||||
}
|
||||
@@ -0,0 +1,927 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Acidic;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Albino;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bandit;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Senior;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Shielded;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.ScrollHolder;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.SeedPouch;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.WandHolster;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfHaggler;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfThorns;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class Badges {
|
||||
|
||||
public static enum Badge {
|
||||
MONSTERS_SLAIN_1( "10 enemies slain", 0 ),
|
||||
MONSTERS_SLAIN_2( "50 enemies slain", 1 ),
|
||||
MONSTERS_SLAIN_3( "150 enemies slain", 2 ),
|
||||
MONSTERS_SLAIN_4( "250 enemies slain", 3 ),
|
||||
GOLD_COLLECTED_1( "100 gold collected", 4 ),
|
||||
GOLD_COLLECTED_2( "500 gold collected", 5 ),
|
||||
GOLD_COLLECTED_3( "2500 gold collected", 6 ),
|
||||
GOLD_COLLECTED_4( "7500 gold collected", 7 ),
|
||||
LEVEL_REACHED_1( "Level 6 reached", 8 ),
|
||||
LEVEL_REACHED_2( "Level 12 reached", 9 ),
|
||||
LEVEL_REACHED_3( "Level 18 reached", 10 ),
|
||||
LEVEL_REACHED_4( "Level 24 reached", 11 ),
|
||||
ALL_POTIONS_IDENTIFIED( "All potions identified", 16 ),
|
||||
ALL_SCROLLS_IDENTIFIED( "All scrolls identified", 17 ),
|
||||
ALL_RINGS_IDENTIFIED( "All rings identified", 18 ),
|
||||
ALL_WANDS_IDENTIFIED( "All wands identified", 19 ),
|
||||
ALL_ITEMS_IDENTIFIED( "All potions, scrolls, rings & wands identified", 35, true ),
|
||||
BAG_BOUGHT_SEED_POUCH,
|
||||
BAG_BOUGHT_SCROLL_HOLDER,
|
||||
BAG_BOUGHT_WAND_HOLSTER,
|
||||
ALL_BAGS_BOUGHT( "All bags bought", 23 ),
|
||||
DEATH_FROM_FIRE( "Death from fire", 24 ),
|
||||
DEATH_FROM_POISON( "Death from poison", 25 ),
|
||||
DEATH_FROM_GAS( "Death from toxic gas", 26 ),
|
||||
DEATH_FROM_HUNGER( "Death from hunger", 27 ),
|
||||
DEATH_FROM_GLYPH( "Death from a glyph", 57 ),
|
||||
DEATH_FROM_FALLING( "Death from falling down", 59 ),
|
||||
YASD( "Death from fire, poison, toxic gas & hunger", 34, true ),
|
||||
BOSS_SLAIN_1_WARRIOR,
|
||||
BOSS_SLAIN_1_MAGE,
|
||||
BOSS_SLAIN_1_ROGUE,
|
||||
BOSS_SLAIN_1_HUNTRESS,
|
||||
BOSS_SLAIN_1( "1st boss slain", 12 ),
|
||||
BOSS_SLAIN_2( "2nd boss slain", 13 ),
|
||||
BOSS_SLAIN_3( "3rd boss slain", 14 ),
|
||||
BOSS_SLAIN_4( "4th boss slain", 15 ),
|
||||
BOSS_SLAIN_1_ALL_CLASSES( "1st boss slain by Warrior, Mage, Rogue & Huntress", 32, true ),
|
||||
BOSS_SLAIN_3_GLADIATOR,
|
||||
BOSS_SLAIN_3_BERSERKER,
|
||||
BOSS_SLAIN_3_WARLOCK,
|
||||
BOSS_SLAIN_3_BATTLEMAGE,
|
||||
BOSS_SLAIN_3_FREERUNNER,
|
||||
BOSS_SLAIN_3_ASSASSIN,
|
||||
BOSS_SLAIN_3_SNIPER,
|
||||
BOSS_SLAIN_3_WARDEN,
|
||||
BOSS_SLAIN_3_ALL_SUBCLASSES(
|
||||
"3rd boss slain by Gladiator, Berserker, Warlock, Battlemage, " +
|
||||
"Freerunner, Assassin, Sniper & Warden", 33, true ),
|
||||
RING_OF_HAGGLER( "Ring of Haggler obtained", 20 ),
|
||||
RING_OF_THORNS( "Ring of Thorns obtained", 21 ),
|
||||
STRENGTH_ATTAINED_1( "13 points of Strength attained", 40 ),
|
||||
STRENGTH_ATTAINED_2( "15 points of Strength attained", 41 ),
|
||||
STRENGTH_ATTAINED_3( "17 points of Strength attained", 42 ),
|
||||
STRENGTH_ATTAINED_4( "19 points of Strength attained", 43 ),
|
||||
FOOD_EATEN_1( "10 pieces of food eaten", 44 ),
|
||||
FOOD_EATEN_2( "20 pieces of food eaten", 45 ),
|
||||
FOOD_EATEN_3( "30 pieces of food eaten", 46 ),
|
||||
FOOD_EATEN_4( "40 pieces of food eaten", 47 ),
|
||||
MASTERY_WARRIOR,
|
||||
MASTERY_MAGE,
|
||||
MASTERY_ROGUE,
|
||||
MASTERY_HUNTRESS,
|
||||
ITEM_LEVEL_1( "Item of level 3 acquired", 48 ),
|
||||
ITEM_LEVEL_2( "Item of level 6 acquired", 49 ),
|
||||
ITEM_LEVEL_3( "Item of level 9 acquired", 50 ),
|
||||
ITEM_LEVEL_4( "Item of level 12 acquired", 51 ),
|
||||
RARE_ALBINO,
|
||||
RARE_BANDIT,
|
||||
RARE_SHIELDED,
|
||||
RARE_SENIOR,
|
||||
RARE_ACIDIC,
|
||||
RARE( "All rare monsters slain", 37, true ),
|
||||
VICTORY_WARRIOR,
|
||||
VICTORY_MAGE,
|
||||
VICTORY_ROGUE,
|
||||
VICTORY_HUNTRESS,
|
||||
VICTORY( "Amulet of Yendor obtained", 22 ),
|
||||
VICTORY_ALL_CLASSES( "Amulet of Yendor obtained by Warrior, Mage, Rogue & Huntress", 36, true ),
|
||||
MASTERY_COMBO( "7-hit combo", 56 ),
|
||||
POTIONS_COOKED_1( "3 potions cooked", 52 ),
|
||||
POTIONS_COOKED_2( "6 potions cooked", 53 ),
|
||||
POTIONS_COOKED_3( "9 potions cooked", 54 ),
|
||||
POTIONS_COOKED_4( "12 potions cooked", 55 ),
|
||||
NO_MONSTERS_SLAIN( "Level completed without killing any monsters", 28 ),
|
||||
GRIM_WEAPON( "Monster killed by a Grim weapon", 29 ),
|
||||
PIRANHAS( "6 piranhas killed", 30 ),
|
||||
NIGHT_HUNTER( "15 monsters killed at nighttime", 58 ),
|
||||
GAMES_PLAYED_1( "10 games played", 60, true ),
|
||||
GAMES_PLAYED_2( "100 games played", 61, true ),
|
||||
GAMES_PLAYED_3( "500 games played", 62, true ),
|
||||
GAMES_PLAYED_4( "2000 games played", 63, true ),
|
||||
HAPPY_END( "Happy end", 38 ),
|
||||
SUPPORTER( "Thanks for your support!", 31, true );
|
||||
|
||||
public boolean meta;
|
||||
|
||||
public String description;
|
||||
public int image;
|
||||
|
||||
private Badge( String description, int image ) {
|
||||
this( description, image, false );
|
||||
}
|
||||
|
||||
private Badge( String description, int image, boolean meta ) {
|
||||
this.description = description;
|
||||
this.image = image;
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
private Badge() {
|
||||
this( "", -1 );
|
||||
}
|
||||
}
|
||||
|
||||
private static HashSet<Badge> global;
|
||||
private static HashSet<Badge> local = new HashSet<Badges.Badge>();
|
||||
|
||||
private static boolean saveNeeded = false;
|
||||
|
||||
public static void reset() {
|
||||
local.clear();
|
||||
loadGlobal();
|
||||
}
|
||||
|
||||
private static final String BADGES_FILE = "badges.dat";
|
||||
private static final String BADGES = "badges";
|
||||
|
||||
private static HashSet<Badge> restore( Bundle bundle ) {
|
||||
HashSet<Badge> badges = new HashSet<Badge>();
|
||||
|
||||
String[] names = bundle.getStringArray( BADGES );
|
||||
for (int i=0; i < names.length; i++) {
|
||||
try {
|
||||
badges.add( Badge.valueOf( names[i] ) );
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
return badges;
|
||||
}
|
||||
|
||||
private static void store( Bundle bundle, HashSet<Badge> badges ) {
|
||||
int count = 0;
|
||||
String names[] = new String[global.size()];
|
||||
|
||||
for (Badge badge:badges) {
|
||||
names[count++] = badge.toString();
|
||||
}
|
||||
bundle.put( BADGES, names );
|
||||
}
|
||||
|
||||
public static void loadLocal( Bundle bundle ) {
|
||||
local = restore( bundle );
|
||||
}
|
||||
|
||||
public static void saveLocal( Bundle bundle ) {
|
||||
store( bundle, local );
|
||||
}
|
||||
|
||||
public static void loadGlobal() {
|
||||
if (global == null) {
|
||||
try {
|
||||
InputStream input = Game.instance.openFileInput( BADGES_FILE );
|
||||
Bundle bundle = Bundle.read( input );
|
||||
input.close();
|
||||
|
||||
global = restore( bundle );
|
||||
|
||||
} catch (IOException e) {
|
||||
global = new HashSet<Badge>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveGlobal() {
|
||||
if (saveNeeded) {
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
store( bundle, global );
|
||||
|
||||
try {
|
||||
OutputStream output = Game.instance.openFileOutput( BADGES_FILE, Game.MODE_PRIVATE );
|
||||
Bundle.write( bundle, output );
|
||||
output.close();
|
||||
saveNeeded = false;
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateMonstersSlain() {
|
||||
Badge badge = null;
|
||||
|
||||
if (!local.contains( Badge.MONSTERS_SLAIN_1 ) && Statistics.enemiesSlain >= 10) {
|
||||
badge = Badge.MONSTERS_SLAIN_1;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.MONSTERS_SLAIN_2 ) && Statistics.enemiesSlain >= 50) {
|
||||
badge = Badge.MONSTERS_SLAIN_2;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.MONSTERS_SLAIN_3 ) && Statistics.enemiesSlain >= 150) {
|
||||
badge = Badge.MONSTERS_SLAIN_3;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.MONSTERS_SLAIN_4 ) && Statistics.enemiesSlain >= 250) {
|
||||
badge = Badge.MONSTERS_SLAIN_4;
|
||||
local.add( badge );
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validateGoldCollected() {
|
||||
Badge badge = null;
|
||||
|
||||
if (!local.contains( Badge.GOLD_COLLECTED_1 ) && Statistics.goldCollected >= 100) {
|
||||
badge = Badge.GOLD_COLLECTED_1;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.GOLD_COLLECTED_2 ) && Statistics.goldCollected >= 500) {
|
||||
badge = Badge.GOLD_COLLECTED_2;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.GOLD_COLLECTED_3 ) && Statistics.goldCollected >= 2500) {
|
||||
badge = Badge.GOLD_COLLECTED_3;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.GOLD_COLLECTED_4 ) && Statistics.goldCollected >= 7500) {
|
||||
badge = Badge.GOLD_COLLECTED_4;
|
||||
local.add( badge );
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validateLevelReached() {
|
||||
Badge badge = null;
|
||||
|
||||
if (!local.contains( Badge.LEVEL_REACHED_1 ) && Dungeon.hero.lvl >= 6) {
|
||||
badge = Badge.LEVEL_REACHED_1;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.LEVEL_REACHED_2 ) && Dungeon.hero.lvl >= 12) {
|
||||
badge = Badge.LEVEL_REACHED_2;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.LEVEL_REACHED_3 ) && Dungeon.hero.lvl >= 18) {
|
||||
badge = Badge.LEVEL_REACHED_3;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.LEVEL_REACHED_4 ) && Dungeon.hero.lvl >= 24) {
|
||||
badge = Badge.LEVEL_REACHED_4;
|
||||
local.add( badge );
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validateStrengthAttained() {
|
||||
Badge badge = null;
|
||||
|
||||
if (!local.contains( Badge.STRENGTH_ATTAINED_1 ) && Dungeon.hero.STR >= 13) {
|
||||
badge = Badge.STRENGTH_ATTAINED_1;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.STRENGTH_ATTAINED_2 ) && Dungeon.hero.STR >= 15) {
|
||||
badge = Badge.STRENGTH_ATTAINED_2;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.STRENGTH_ATTAINED_3 ) && Dungeon.hero.STR >= 17) {
|
||||
badge = Badge.STRENGTH_ATTAINED_3;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.STRENGTH_ATTAINED_4 ) && Dungeon.hero.STR >= 19) {
|
||||
badge = Badge.STRENGTH_ATTAINED_4;
|
||||
local.add( badge );
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validateFoodEaten() {
|
||||
Badge badge = null;
|
||||
|
||||
if (!local.contains( Badge.FOOD_EATEN_1 ) && Statistics.foodEaten >= 10) {
|
||||
badge = Badge.FOOD_EATEN_1;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.FOOD_EATEN_2 ) && Statistics.foodEaten >= 20) {
|
||||
badge = Badge.FOOD_EATEN_2;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.FOOD_EATEN_3 ) && Statistics.foodEaten >= 30) {
|
||||
badge = Badge.FOOD_EATEN_3;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.FOOD_EATEN_4 ) && Statistics.foodEaten >= 40) {
|
||||
badge = Badge.FOOD_EATEN_4;
|
||||
local.add( badge );
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validatePotionsCooked() {
|
||||
Badge badge = null;
|
||||
|
||||
if (!local.contains( Badge.POTIONS_COOKED_1 ) && Statistics.potionsCooked >= 3) {
|
||||
badge = Badge.POTIONS_COOKED_1;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.POTIONS_COOKED_2 ) && Statistics.potionsCooked >= 6) {
|
||||
badge = Badge.POTIONS_COOKED_2;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.POTIONS_COOKED_3 ) && Statistics.potionsCooked >= 9) {
|
||||
badge = Badge.POTIONS_COOKED_3;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.POTIONS_COOKED_4 ) && Statistics.potionsCooked >= 12) {
|
||||
badge = Badge.POTIONS_COOKED_4;
|
||||
local.add( badge );
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validatePiranhasKilled() {
|
||||
Badge badge = null;
|
||||
|
||||
if (!local.contains( Badge.PIRANHAS ) && Statistics.piranhasKilled >= 6) {
|
||||
badge = Badge.PIRANHAS;
|
||||
local.add( badge );
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validateItemLevelAquired( Item item ) {
|
||||
|
||||
// This method should be called:
|
||||
// 1) When an item is obtained (Item.collect)
|
||||
// 2) When an item is upgraded (ScrollOfUpgrade, ScrollOfWeaponUpgrade, ShortSword, WandOfMagicMissile)
|
||||
// 3) When an item is identified
|
||||
if (!item.levelKnown) {
|
||||
return;
|
||||
}
|
||||
|
||||
Badge badge = null;
|
||||
|
||||
if (!local.contains( Badge.ITEM_LEVEL_1 ) && item.level >= 3) {
|
||||
badge = Badge.ITEM_LEVEL_1;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.ITEM_LEVEL_2 ) && item.level >= 6) {
|
||||
badge = Badge.ITEM_LEVEL_2;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.ITEM_LEVEL_3 ) && item.level >= 9) {
|
||||
badge = Badge.ITEM_LEVEL_3;
|
||||
local.add( badge );
|
||||
}
|
||||
if (!local.contains( Badge.ITEM_LEVEL_4 ) && item.level >= 12) {
|
||||
badge = Badge.ITEM_LEVEL_4;
|
||||
local.add( badge );
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validateAllPotionsIdentified() {
|
||||
if (Dungeon.hero != null && Dungeon.hero.isAlive() &&
|
||||
!local.contains( Badge.ALL_POTIONS_IDENTIFIED ) && Potion.allKnown()) {
|
||||
|
||||
Badge badge = Badge.ALL_POTIONS_IDENTIFIED;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
validateAllItemsIdentified();
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateAllScrollsIdentified() {
|
||||
if (Dungeon.hero != null && Dungeon.hero.isAlive() &&
|
||||
!local.contains( Badge.ALL_SCROLLS_IDENTIFIED ) && Scroll.allKnown()) {
|
||||
|
||||
Badge badge = Badge.ALL_SCROLLS_IDENTIFIED;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
validateAllItemsIdentified();
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateAllRingsIdentified() {
|
||||
if (Dungeon.hero != null && Dungeon.hero.isAlive() &&
|
||||
!local.contains( Badge.ALL_RINGS_IDENTIFIED ) && Ring.allKnown()) {
|
||||
|
||||
Badge badge = Badge.ALL_RINGS_IDENTIFIED;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
validateAllItemsIdentified();
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateAllWandsIdentified() {
|
||||
if (Dungeon.hero != null && Dungeon.hero.isAlive() &&
|
||||
!local.contains( Badge.ALL_WANDS_IDENTIFIED ) && Wand.allKnown()) {
|
||||
|
||||
Badge badge = Badge.ALL_WANDS_IDENTIFIED;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
validateAllItemsIdentified();
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateAllBagsBought( Item bag ) {
|
||||
|
||||
Badge badge = null;
|
||||
if (bag instanceof SeedPouch) {
|
||||
badge = Badge.BAG_BOUGHT_SEED_POUCH;
|
||||
} else if (bag instanceof ScrollHolder) {
|
||||
badge = Badge.BAG_BOUGHT_SCROLL_HOLDER;
|
||||
} else if (bag instanceof WandHolster) {
|
||||
badge = Badge.BAG_BOUGHT_WAND_HOLSTER;
|
||||
}
|
||||
|
||||
if (badge != null) {
|
||||
|
||||
local.add( badge );
|
||||
|
||||
if (!local.contains( Badge.ALL_BAGS_BOUGHT ) &&
|
||||
local.contains( Badge.BAG_BOUGHT_SCROLL_HOLDER ) &&
|
||||
local.contains( Badge.BAG_BOUGHT_SEED_POUCH ) &&
|
||||
local.contains( Badge.BAG_BOUGHT_WAND_HOLSTER )) {
|
||||
|
||||
badge = Badge.ALL_BAGS_BOUGHT;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateAllItemsIdentified() {
|
||||
if (!global.contains( Badge.ALL_ITEMS_IDENTIFIED ) &&
|
||||
global.contains( Badge.ALL_POTIONS_IDENTIFIED ) &&
|
||||
global.contains( Badge.ALL_SCROLLS_IDENTIFIED ) &&
|
||||
global.contains( Badge.ALL_RINGS_IDENTIFIED ) &&
|
||||
global.contains( Badge.ALL_WANDS_IDENTIFIED )) {
|
||||
|
||||
Badge badge = Badge.ALL_ITEMS_IDENTIFIED;
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateDeathFromFire() {
|
||||
Badge badge = Badge.DEATH_FROM_FIRE;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
validateYASD();
|
||||
}
|
||||
|
||||
public static void validateDeathFromPoison() {
|
||||
Badge badge = Badge.DEATH_FROM_POISON;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
validateYASD();
|
||||
}
|
||||
|
||||
public static void validateDeathFromGas() {
|
||||
Badge badge = Badge.DEATH_FROM_GAS;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
validateYASD();
|
||||
}
|
||||
|
||||
public static void validateDeathFromHunger() {
|
||||
Badge badge = Badge.DEATH_FROM_HUNGER;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
validateYASD();
|
||||
}
|
||||
|
||||
public static void validateDeathFromGlyph() {
|
||||
Badge badge = Badge.DEATH_FROM_GLYPH;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validateDeathFromFalling() {
|
||||
Badge badge = Badge.DEATH_FROM_FALLING;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
private static void validateYASD() {
|
||||
if (global.contains( Badge.DEATH_FROM_FIRE ) &&
|
||||
global.contains( Badge.DEATH_FROM_POISON ) &&
|
||||
global.contains( Badge.DEATH_FROM_GAS ) &&
|
||||
global.contains( Badge.DEATH_FROM_HUNGER)) {
|
||||
|
||||
Badge badge = Badge.YASD;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateBossSlain() {
|
||||
Badge badge = null;
|
||||
switch (Dungeon.depth) {
|
||||
case 5:
|
||||
badge = Badge.BOSS_SLAIN_1;
|
||||
break;
|
||||
case 10:
|
||||
badge = Badge.BOSS_SLAIN_2;
|
||||
break;
|
||||
case 15:
|
||||
badge = Badge.BOSS_SLAIN_3;
|
||||
break;
|
||||
case 20:
|
||||
badge = Badge.BOSS_SLAIN_4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (badge != null) {
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
|
||||
if (badge == Badge.BOSS_SLAIN_1) {
|
||||
switch (Dungeon.hero.heroClass) {
|
||||
case WARRIOR:
|
||||
badge = Badge.BOSS_SLAIN_1_WARRIOR;
|
||||
break;
|
||||
case MAGE:
|
||||
badge = Badge.BOSS_SLAIN_1_MAGE;
|
||||
break;
|
||||
case ROGUE:
|
||||
badge = Badge.BOSS_SLAIN_1_ROGUE;
|
||||
break;
|
||||
case HUNTRESS:
|
||||
badge = Badge.BOSS_SLAIN_1_HUNTRESS;
|
||||
break;
|
||||
}
|
||||
local.add( badge );
|
||||
if (!global.contains( badge )) {
|
||||
global.add( badge );
|
||||
saveNeeded = true;
|
||||
}
|
||||
|
||||
if (global.contains( Badge.BOSS_SLAIN_1_WARRIOR ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_1_MAGE ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_1_ROGUE ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_1_HUNTRESS)) {
|
||||
|
||||
badge = Badge.BOSS_SLAIN_1_ALL_CLASSES;
|
||||
if (!global.contains( badge )) {
|
||||
displayBadge( badge );
|
||||
global.add( badge );
|
||||
saveNeeded = true;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (badge == Badge.BOSS_SLAIN_3) {
|
||||
switch (Dungeon.hero.subClass) {
|
||||
case GLADIATOR:
|
||||
badge = Badge.BOSS_SLAIN_3_GLADIATOR;
|
||||
break;
|
||||
case BERSERKER:
|
||||
badge = Badge.BOSS_SLAIN_3_BERSERKER;
|
||||
break;
|
||||
case WARLOCK:
|
||||
badge = Badge.BOSS_SLAIN_3_WARLOCK;
|
||||
break;
|
||||
case BATTLEMAGE:
|
||||
badge = Badge.BOSS_SLAIN_3_BATTLEMAGE;
|
||||
break;
|
||||
case FREERUNNER:
|
||||
badge = Badge.BOSS_SLAIN_3_FREERUNNER;
|
||||
break;
|
||||
case ASSASSIN:
|
||||
badge = Badge.BOSS_SLAIN_3_ASSASSIN;
|
||||
break;
|
||||
case SNIPER:
|
||||
badge = Badge.BOSS_SLAIN_3_SNIPER;
|
||||
break;
|
||||
case WARDEN:
|
||||
badge = Badge.BOSS_SLAIN_3_WARDEN;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
local.add( badge );
|
||||
if (!global.contains( badge )) {
|
||||
global.add( badge );
|
||||
saveNeeded = true;
|
||||
}
|
||||
|
||||
if (global.contains( Badge.BOSS_SLAIN_3_GLADIATOR ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_3_BERSERKER ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_3_WARLOCK ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_3_BATTLEMAGE ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_3_FREERUNNER ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_3_ASSASSIN ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_3_SNIPER ) &&
|
||||
global.contains( Badge.BOSS_SLAIN_3_WARDEN )) {
|
||||
|
||||
badge = Badge.BOSS_SLAIN_3_ALL_SUBCLASSES;
|
||||
if (!global.contains( badge )) {
|
||||
displayBadge( badge );
|
||||
global.add( badge );
|
||||
saveNeeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateMastery() {
|
||||
|
||||
Badge badge = null;
|
||||
switch (Dungeon.hero.heroClass) {
|
||||
case WARRIOR:
|
||||
badge = Badge.MASTERY_WARRIOR;
|
||||
break;
|
||||
case MAGE:
|
||||
badge = Badge.MASTERY_MAGE;
|
||||
break;
|
||||
case ROGUE:
|
||||
badge = Badge.MASTERY_ROGUE;
|
||||
break;
|
||||
case HUNTRESS:
|
||||
badge = Badge.MASTERY_HUNTRESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!global.contains( badge )) {
|
||||
global.add( badge );
|
||||
saveNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateMasteryCombo( int n ) {
|
||||
if (!local.contains( Badge.MASTERY_COMBO ) && n == 7) {
|
||||
Badge badge = Badge.MASTERY_COMBO;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateRingOfHaggler() {
|
||||
if (!local.contains( Badge.RING_OF_HAGGLER ) && new RingOfHaggler().isKnown()) {
|
||||
Badge badge = Badge.RING_OF_HAGGLER;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateRingOfThorns() {
|
||||
if (!local.contains( Badge.RING_OF_THORNS ) && new RingOfThorns().isKnown()) {
|
||||
Badge badge = Badge.RING_OF_THORNS;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateRare( Mob mob ) {
|
||||
|
||||
Badge badge = null;
|
||||
if (mob instanceof Albino) {
|
||||
badge = Badge.RARE_ALBINO;
|
||||
} else if (mob instanceof Bandit) {
|
||||
badge = Badge.RARE_BANDIT;
|
||||
} else if (mob instanceof Shielded) {
|
||||
badge = Badge.RARE_SHIELDED;
|
||||
} else if (mob instanceof Senior) {
|
||||
badge = Badge.RARE_SENIOR;
|
||||
} else if (mob instanceof Acidic) {
|
||||
badge = Badge.RARE_ACIDIC;
|
||||
}
|
||||
if (!global.contains( badge )) {
|
||||
global.add( badge );
|
||||
saveNeeded = true;
|
||||
}
|
||||
|
||||
if (global.contains( Badge.RARE_ALBINO ) &&
|
||||
global.contains( Badge.RARE_BANDIT ) &&
|
||||
global.contains( Badge.RARE_SHIELDED ) &&
|
||||
global.contains( Badge.RARE_SENIOR ) &&
|
||||
global.contains( Badge.RARE_ACIDIC )) {
|
||||
|
||||
badge = Badge.RARE;
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateVictory() {
|
||||
|
||||
Badge badge = Badge.VICTORY;
|
||||
displayBadge( badge );
|
||||
|
||||
switch (Dungeon.hero.heroClass) {
|
||||
case WARRIOR:
|
||||
badge = Badge.VICTORY_WARRIOR;
|
||||
break;
|
||||
case MAGE:
|
||||
badge = Badge.VICTORY_MAGE;
|
||||
break;
|
||||
case ROGUE:
|
||||
badge = Badge.VICTORY_ROGUE;
|
||||
break;
|
||||
case HUNTRESS:
|
||||
badge = Badge.VICTORY_HUNTRESS;
|
||||
break;
|
||||
}
|
||||
local.add( badge );
|
||||
if (!global.contains( badge )) {
|
||||
global.add( badge );
|
||||
saveNeeded = true;
|
||||
}
|
||||
|
||||
if (global.contains( Badge.VICTORY_WARRIOR ) &&
|
||||
global.contains( Badge.VICTORY_MAGE ) &&
|
||||
global.contains( Badge.VICTORY_ROGUE ) &&
|
||||
global.contains( Badge.VICTORY_HUNTRESS )) {
|
||||
|
||||
badge = Badge.VICTORY_ALL_CLASSES;
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateNoKilling() {
|
||||
if (!local.contains( Badge.NO_MONSTERS_SLAIN ) && Statistics.completedWithNoKilling) {
|
||||
Badge badge = Badge.NO_MONSTERS_SLAIN;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateGrimWeapon() {
|
||||
if (!local.contains( Badge.GRIM_WEAPON )) {
|
||||
Badge badge = Badge.GRIM_WEAPON;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateNightHunter() {
|
||||
if (!local.contains( Badge.NIGHT_HUNTER ) && Statistics.nightHunt >= 15) {
|
||||
Badge badge = Badge.NIGHT_HUNTER;
|
||||
local.add( badge );
|
||||
displayBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateSupporter() {
|
||||
|
||||
global.add( Badge.SUPPORTER );
|
||||
saveNeeded = true;
|
||||
|
||||
PixelScene.showBadge( Badge.SUPPORTER );
|
||||
}
|
||||
|
||||
public static void validateGamesPlayed() {
|
||||
Badge badge = null;
|
||||
if (Rankings.INSTANCE.totalNumber >= 10) {
|
||||
badge = Badge.GAMES_PLAYED_1;
|
||||
}
|
||||
if (Rankings.INSTANCE.totalNumber >= 100) {
|
||||
badge = Badge.GAMES_PLAYED_2;
|
||||
}
|
||||
if (Rankings.INSTANCE.totalNumber >= 500) {
|
||||
badge = Badge.GAMES_PLAYED_3;
|
||||
}
|
||||
if (Rankings.INSTANCE.totalNumber >= 2000) {
|
||||
badge = Badge.GAMES_PLAYED_4;
|
||||
}
|
||||
|
||||
displayBadge( badge );
|
||||
}
|
||||
|
||||
public static void validateHappyEnd() {
|
||||
displayBadge( Badge.HAPPY_END );
|
||||
}
|
||||
|
||||
private static void displayBadge( Badge badge ) {
|
||||
|
||||
if (badge == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (global.contains( badge )) {
|
||||
|
||||
if (!badge.meta) {
|
||||
GLog.h( "Badge endorsed: %s", badge.description );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
global.add( badge );
|
||||
saveNeeded = true;
|
||||
|
||||
if (badge.meta) {
|
||||
GLog.h( "New super badge: %s", badge.description );
|
||||
} else {
|
||||
GLog.h( "New badge: %s", badge.description );
|
||||
}
|
||||
PixelScene.showBadge( badge );
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isUnlocked( Badge badge ) {
|
||||
return global.contains( badge );
|
||||
}
|
||||
|
||||
public static void disown( Badge badge ) {
|
||||
loadGlobal();
|
||||
global.remove( badge );
|
||||
saveNeeded = true;
|
||||
}
|
||||
|
||||
public static List<Badge> filtered( boolean global ) {
|
||||
|
||||
HashSet<Badge> filtered = new HashSet<Badge>( global ? Badges.global : Badges.local );
|
||||
|
||||
if (!global) {
|
||||
Iterator<Badge> iterator = filtered.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Badge badge = iterator.next();
|
||||
if (badge.meta) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leaveBest( filtered, Badge.MONSTERS_SLAIN_1, Badge.MONSTERS_SLAIN_2, Badge.MONSTERS_SLAIN_3, Badge.MONSTERS_SLAIN_4 );
|
||||
leaveBest( filtered, Badge.GOLD_COLLECTED_1, Badge.GOLD_COLLECTED_2, Badge.GOLD_COLLECTED_3, Badge.GOLD_COLLECTED_4 );
|
||||
leaveBest( filtered, Badge.BOSS_SLAIN_1, Badge.BOSS_SLAIN_2, Badge.BOSS_SLAIN_3, Badge.BOSS_SLAIN_4 );
|
||||
leaveBest( filtered, Badge.LEVEL_REACHED_1, Badge.LEVEL_REACHED_2, Badge.LEVEL_REACHED_3, Badge.LEVEL_REACHED_4 );
|
||||
leaveBest( filtered, Badge.STRENGTH_ATTAINED_1, Badge.STRENGTH_ATTAINED_2, Badge.STRENGTH_ATTAINED_3, Badge.STRENGTH_ATTAINED_4 );
|
||||
leaveBest( filtered, Badge.FOOD_EATEN_1, Badge.FOOD_EATEN_2, Badge.FOOD_EATEN_3, Badge.FOOD_EATEN_4 );
|
||||
leaveBest( filtered, Badge.ITEM_LEVEL_1, Badge.ITEM_LEVEL_2, Badge.ITEM_LEVEL_3, Badge.ITEM_LEVEL_4 );
|
||||
leaveBest( filtered, Badge.POTIONS_COOKED_1, Badge.POTIONS_COOKED_2, Badge.POTIONS_COOKED_3, Badge.POTIONS_COOKED_4 );
|
||||
leaveBest( filtered, Badge.BOSS_SLAIN_1_ALL_CLASSES, Badge.BOSS_SLAIN_3_ALL_SUBCLASSES );
|
||||
leaveBest( filtered, Badge.DEATH_FROM_FIRE, Badge.YASD );
|
||||
leaveBest( filtered, Badge.DEATH_FROM_GAS, Badge.YASD );
|
||||
leaveBest( filtered, Badge.DEATH_FROM_HUNGER, Badge.YASD );
|
||||
leaveBest( filtered, Badge.DEATH_FROM_POISON, Badge.YASD );
|
||||
leaveBest( filtered, Badge.VICTORY, Badge.VICTORY_ALL_CLASSES );
|
||||
leaveBest( filtered, Badge.GAMES_PLAYED_1, Badge.GAMES_PLAYED_2, Badge.GAMES_PLAYED_3, Badge.GAMES_PLAYED_4 );
|
||||
|
||||
ArrayList<Badge> list = new ArrayList<Badge>( filtered );
|
||||
Collections.sort( list );
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void leaveBest( HashSet<Badge> list, Badge...badges ) {
|
||||
for (int i=badges.length-1; i > 0; i--) {
|
||||
if (list.contains( badges[i])) {
|
||||
for (int j=0; j < i; j++) {
|
||||
list.remove( badges[j] );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Bones {
|
||||
|
||||
private static final String BONES_FILE = "bones.dat";
|
||||
|
||||
private static final String LEVEL = "level";
|
||||
private static final String ITEM = "item";
|
||||
|
||||
private static int depth = -1;
|
||||
private static Item item;
|
||||
|
||||
public static void leave() {
|
||||
|
||||
item = null;
|
||||
switch (Random.Int( 4 )) {
|
||||
case 0:
|
||||
item = Dungeon.hero.belongings.weapon;
|
||||
break;
|
||||
case 1:
|
||||
item = Dungeon.hero.belongings.armor;
|
||||
break;
|
||||
case 2:
|
||||
item = Dungeon.hero.belongings.ring1;
|
||||
break;
|
||||
case 3:
|
||||
item = Dungeon.hero.belongings.ring2;
|
||||
break;
|
||||
}
|
||||
if (item == null) {
|
||||
if (Dungeon.gold > 0) {
|
||||
item = new Gold( Random.IntRange( 1, Dungeon.gold ) );
|
||||
} else {
|
||||
item = new Gold( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
depth = Dungeon.depth;
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.put( LEVEL, depth );
|
||||
bundle.put( ITEM, item );
|
||||
|
||||
try {
|
||||
OutputStream output = Game.instance.openFileOutput( BONES_FILE, Game.MODE_PRIVATE );
|
||||
Bundle.write( bundle, output );
|
||||
output.close();
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static Item get() {
|
||||
if (depth == -1) {
|
||||
|
||||
try {
|
||||
InputStream input = Game.instance.openFileInput( BONES_FILE ) ;
|
||||
Bundle bundle = Bundle.read( input );
|
||||
input.close();
|
||||
|
||||
depth = bundle.getInt( LEVEL );
|
||||
item = (Item)bundle.get( ITEM );
|
||||
|
||||
return get();
|
||||
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (depth == Dungeon.depth) {
|
||||
Game.instance.deleteFile( BONES_FILE );
|
||||
depth = 0;
|
||||
|
||||
if (!item.stackable) {
|
||||
item.cursed = true;
|
||||
item.cursedKnown = true;
|
||||
if (item.isUpgradable()) {
|
||||
int lvl = (Dungeon.depth - 1) * 3 / 5 + 1;
|
||||
if (lvl < item.level) {
|
||||
item.degrade( item.level - lvl );
|
||||
}
|
||||
item.levelKnown = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (item instanceof Ring) {
|
||||
((Ring)item).syncGem();
|
||||
}
|
||||
|
||||
return item;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.NinePatch;
|
||||
|
||||
public class Chrome {
|
||||
|
||||
public enum Type {
|
||||
TOAST,
|
||||
TOAST_TR,
|
||||
WINDOW,
|
||||
BUTTON,
|
||||
TAG,
|
||||
GEM,
|
||||
SCROLL,
|
||||
TAB_SET,
|
||||
TAB_SELECTED,
|
||||
TAB_UNSELECTED,
|
||||
SURFACE
|
||||
};
|
||||
|
||||
public static NinePatch get( Type type ) {
|
||||
switch (type) {
|
||||
case WINDOW:
|
||||
return new NinePatch( Assets.CHROME, 0, 0, 22, 22, 7 );
|
||||
case TOAST:
|
||||
return new NinePatch( Assets.CHROME, 22, 0, 18, 18, 5 );
|
||||
case TOAST_TR:
|
||||
return new NinePatch( Assets.CHROME, 40, 0, 18, 18, 5 );
|
||||
case BUTTON:
|
||||
return new NinePatch( Assets.CHROME, 58, 0, 4, 4, 1 );
|
||||
case TAG:
|
||||
return new NinePatch( Assets.CHROME, 22, 18, 16, 14, 3 );
|
||||
case GEM:
|
||||
return new NinePatch( Assets.CHROME, 0, 32, 32, 32, 13 );
|
||||
case SCROLL:
|
||||
return new NinePatch( Assets.CHROME, 32, 32, 32, 32, 5, 11, 5, 11 );
|
||||
case TAB_SET:
|
||||
return new NinePatch( Assets.CHROME, 64, 0, 22, 22, 7, 7, 7, 7 );
|
||||
case TAB_SELECTED:
|
||||
return new NinePatch( Assets.CHROME, 64, 22, 10, 14, 4, 7, 4, 6 );
|
||||
case TAB_UNSELECTED:
|
||||
return new NinePatch( Assets.CHROME, 74, 22, 10, 14, 4, 7, 4, 6 );
|
||||
case SURFACE:
|
||||
return new NinePatch( Assets.CHROME, 86, 0, 22, 22, 5 );
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,690 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Ankh;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.CavesBossLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.CavesLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.CityBossLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.CityLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.DeadEndLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.HallsBossLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.HallsLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.LastLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.LastShopLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.PrisonBossLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.PrisonLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.SewerBossLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.SewerLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.StartScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndResurrect;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.PathFinder;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Dungeon {
|
||||
|
||||
private static final String NO_TIPS = "The text is indecipherable...";
|
||||
private static final String[] TIPS = {
|
||||
"Don't overestimate your strength, use weapons and armor you can handle.",
|
||||
"Not all doors in the dungeon are visible at first sight. If you are stuck, search for hidden doors.",
|
||||
"Remember, that raising your strength is not the only way to access better equipment, you can go " +
|
||||
"the other way lowering its strength requirement with Scrolls of Upgrade.",
|
||||
"You can spend your gold in shops on deeper levels of the dungeon. The first one is on the 6th level.",
|
||||
|
||||
"Beware of Goo!",
|
||||
|
||||
"Pixel-Mart - all you need for successful adventure!",
|
||||
"Identify your potions and scrolls as soon as possible. Don't put it off to the moment " +
|
||||
"when you actually need them.",
|
||||
"Being hungry doesn't hurt, but starving does hurt.",
|
||||
"Surprise attack has a better chance to hit. For example, you can ambush your enemy behind " +
|
||||
"a closed door when you know it is approaching.",
|
||||
|
||||
"Don't let The Tengu out!",
|
||||
|
||||
"Pixel-Mart. Spend money. Live longer.",
|
||||
"When you're attacked by several monsters at the same time, try to retreat behind a door.",
|
||||
"If you are burning, you can't put out the fire in the water while levitating.",
|
||||
"There is no sense in possessing more than one Ankh at the same time, because you will lose them upon resurrecting.",
|
||||
|
||||
"DANGER! Heavy machinery can cause injury, loss of limbs or death!",
|
||||
|
||||
"Pixel-Mart. A safer life in dungeon.",
|
||||
"When you upgrade an enchanted weapon, there is a chance to destroy that enchantment.",
|
||||
"In a Well of Transmutation you can get an item, that cannot be obtained otherwise.",
|
||||
"The only way to enchant a weapon is by upgrading it with a Scroll of Weapon Upgrade.",
|
||||
|
||||
"No weapons allowed in the presence of His Majesty!",
|
||||
|
||||
"Pixel-Mart. Special prices for demon hunters!",
|
||||
"The text is written in demonic language.",
|
||||
"The text is written in demonic language.",
|
||||
"The text is written in demonic language."
|
||||
};
|
||||
|
||||
private static final String TXT_DEAD_END =
|
||||
"What are you doing here?!";
|
||||
|
||||
public static int potionOfStrength;
|
||||
public static int scrollsOfUpgrade;
|
||||
public static int arcaneStyli;
|
||||
public static boolean dewVial; // true if the dew vial can be spawned
|
||||
public static int transmutation; // depth number for a well of transmutation
|
||||
|
||||
|
||||
public static Hero hero;
|
||||
public static Level level;
|
||||
|
||||
// Either� Item or Class<? extends Item>
|
||||
public static Object quickslot;
|
||||
|
||||
public static int depth;
|
||||
public static int gold;
|
||||
// Reason of death
|
||||
public static String resultDescription;
|
||||
|
||||
public static HashSet<Integer> chapters;
|
||||
|
||||
// Hero's field of view
|
||||
public static boolean[] visible = new boolean[Level.LENGTH];
|
||||
|
||||
public static boolean nightMode;
|
||||
|
||||
public static void init() {
|
||||
|
||||
Actor.clear();
|
||||
|
||||
PathFinder.setMapSize( Level.WIDTH, Level.HEIGHT );
|
||||
|
||||
Scroll.initLabels();
|
||||
Potion.initColors();
|
||||
Wand.initWoods();
|
||||
Ring.initGems();
|
||||
|
||||
Statistics.reset();
|
||||
Journal.reset();
|
||||
|
||||
depth = 0;
|
||||
gold = 0;
|
||||
|
||||
potionOfStrength = 0;
|
||||
scrollsOfUpgrade = 0;
|
||||
arcaneStyli = 0;
|
||||
dewVial = true;
|
||||
transmutation = Random.IntRange( 6, 14 );
|
||||
|
||||
chapters = new HashSet<Integer>();
|
||||
|
||||
Ghost.Quest.reset();
|
||||
Wandmaker.Quest.reset();
|
||||
Blacksmith.Quest.reset();
|
||||
Imp.Quest.reset();
|
||||
|
||||
Room.shuffleTypes();
|
||||
|
||||
hero = new Hero();
|
||||
hero.live();
|
||||
|
||||
Badges.reset();
|
||||
|
||||
StartScene.curClass.initHero( hero );
|
||||
}
|
||||
|
||||
public static Level newLevel() {
|
||||
|
||||
Dungeon.level = null;
|
||||
Actor.clear();
|
||||
|
||||
depth++;
|
||||
if (depth > Statistics.deepestFloor) {
|
||||
Statistics.deepestFloor = depth;
|
||||
|
||||
if (Statistics.qualifiedForNoKilling) {
|
||||
Statistics.completedWithNoKilling = true;
|
||||
} else {
|
||||
Statistics.completedWithNoKilling = false;
|
||||
}
|
||||
}
|
||||
|
||||
Arrays.fill( visible, false );
|
||||
|
||||
Level level;
|
||||
switch (depth) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
level = new SewerLevel();
|
||||
break;
|
||||
case 5:
|
||||
level = new SewerBossLevel();
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
level = new PrisonLevel();
|
||||
break;
|
||||
case 10:
|
||||
level = new PrisonBossLevel();
|
||||
break;
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
level = new CavesLevel();
|
||||
break;
|
||||
case 15:
|
||||
level = new CavesBossLevel();
|
||||
break;
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
level = new CityLevel();
|
||||
break;
|
||||
case 20:
|
||||
level = new CityBossLevel();
|
||||
break;
|
||||
case 21:
|
||||
level = new LastShopLevel();
|
||||
break;
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
level = new HallsLevel();
|
||||
break;
|
||||
case 25:
|
||||
level = new HallsBossLevel();
|
||||
break;
|
||||
case 26:
|
||||
level = new LastLevel();
|
||||
break;
|
||||
default:
|
||||
level = new DeadEndLevel();
|
||||
Statistics.deepestFloor--;
|
||||
}
|
||||
|
||||
level.create();
|
||||
|
||||
Statistics.qualifiedForNoKilling = !bossLevel();
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
public static void resetLevel() {
|
||||
|
||||
Actor.clear();
|
||||
|
||||
Arrays.fill( visible, false );
|
||||
|
||||
level.reset();
|
||||
switchLevel( level, level.entrance );
|
||||
}
|
||||
|
||||
public static String tip() {
|
||||
|
||||
if (level instanceof DeadEndLevel) {
|
||||
|
||||
return TXT_DEAD_END;
|
||||
|
||||
} else {
|
||||
|
||||
int index = depth - 1;
|
||||
|
||||
if (index < TIPS.length) {
|
||||
return TIPS[index];
|
||||
} else {
|
||||
return NO_TIPS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shopOnLevel() {
|
||||
return depth == 6 || depth == 11 || depth == 16;
|
||||
}
|
||||
|
||||
public static boolean bossLevel() {
|
||||
return bossLevel( depth );
|
||||
}
|
||||
|
||||
public static boolean bossLevel( int depth ) {
|
||||
return depth == 5 || depth == 10 || depth == 15 || depth == 20 || depth == 25;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void switchLevel( final Level level, int pos ) {
|
||||
|
||||
nightMode = new Date().getHours() < 7;
|
||||
|
||||
Dungeon.level = level;
|
||||
Actor.init();
|
||||
|
||||
Actor respawner = level.respawner();
|
||||
if (respawner != null) {
|
||||
Actor.add( level.respawner() );
|
||||
}
|
||||
|
||||
hero.pos = pos != -1 ? pos : level.exit;
|
||||
|
||||
Light light = hero.buff( Light.class );
|
||||
hero.viewDistance = light == null ? level.viewDistance : Math.max( Light.DISTANCE, level.viewDistance );
|
||||
|
||||
observe();
|
||||
}
|
||||
|
||||
public static boolean posNeeded() {
|
||||
int[] quota = {4, 2, 9, 4, 14, 6, 19, 8, 24, 9};
|
||||
return chance( quota, potionOfStrength );
|
||||
}
|
||||
|
||||
public static boolean soeNeeded() {
|
||||
int[] quota = {5, 3, 10, 6, 15, 9, 20, 12, 25, 13};
|
||||
return chance( quota, scrollsOfUpgrade );
|
||||
}
|
||||
|
||||
private static boolean chance( int[] quota, int number ) {
|
||||
|
||||
for (int i=0; i < quota.length; i += 2) {
|
||||
int qDepth = quota[i];
|
||||
if (depth <= qDepth) {
|
||||
int qNumber = quota[i + 1];
|
||||
return Random.Float() < (float)(qNumber - number) / (qDepth - depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean asNeeded() {
|
||||
return Random.Int( 12 * (1 + arcaneStyli) ) < depth;
|
||||
}
|
||||
|
||||
private static final String RG_GAME_FILE = "game.dat";
|
||||
private static final String RG_DEPTH_FILE = "depth%d.dat";
|
||||
|
||||
private static final String WR_GAME_FILE = "warrior.dat";
|
||||
private static final String WR_DEPTH_FILE = "warrior%d.dat";
|
||||
|
||||
private static final String MG_GAME_FILE = "mage.dat";
|
||||
private static final String MG_DEPTH_FILE = "mage%d.dat";
|
||||
|
||||
private static final String RN_GAME_FILE = "ranger.dat";
|
||||
private static final String RN_DEPTH_FILE = "ranger%d.dat";
|
||||
|
||||
private static final String VERSION = "version";
|
||||
private static final String HERO = "hero";
|
||||
private static final String GOLD = "gold";
|
||||
private static final String DEPTH = "depth";
|
||||
private static final String QUICKSLOT = "quickslot";
|
||||
private static final String LEVEL = "level";
|
||||
private static final String POS = "potionsOfStrength";
|
||||
private static final String SOU = "scrollsOfEnhancement";
|
||||
private static final String AS = "arcaneStyli";
|
||||
private static final String DV = "dewVial";
|
||||
private static final String WT = "transmutation";
|
||||
private static final String CHAPTERS = "chapters";
|
||||
private static final String QUESTS = "quests";
|
||||
private static final String BADGES = "badges";
|
||||
|
||||
public static String gameFile( HeroClass cl ) {
|
||||
switch (cl) {
|
||||
case WARRIOR:
|
||||
return WR_GAME_FILE;
|
||||
case MAGE:
|
||||
return MG_GAME_FILE;
|
||||
case HUNTRESS:
|
||||
return RN_GAME_FILE;
|
||||
default:
|
||||
return RG_GAME_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
private static String depthFile( HeroClass cl ) {
|
||||
switch (cl) {
|
||||
case WARRIOR:
|
||||
return WR_DEPTH_FILE;
|
||||
case MAGE:
|
||||
return MG_DEPTH_FILE;
|
||||
case HUNTRESS:
|
||||
return RN_DEPTH_FILE;
|
||||
default:
|
||||
return RG_DEPTH_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveGame( String fileName ) throws IOException {
|
||||
try {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
bundle.put( VERSION, Game.version );
|
||||
bundle.put( HERO, hero );
|
||||
bundle.put( GOLD, gold );
|
||||
bundle.put( DEPTH, depth );
|
||||
|
||||
bundle.put( POS, potionOfStrength );
|
||||
bundle.put( SOU, scrollsOfUpgrade );
|
||||
bundle.put( AS, arcaneStyli );
|
||||
bundle.put( DV, dewVial );
|
||||
bundle.put( WT, transmutation );
|
||||
|
||||
int count = 0;
|
||||
int ids[] = new int[chapters.size()];
|
||||
for (Integer id : chapters) {
|
||||
ids[count++] = id;
|
||||
}
|
||||
bundle.put( CHAPTERS, ids );
|
||||
|
||||
Bundle quests = new Bundle();
|
||||
Ghost .Quest.storeInBundle( quests );
|
||||
Wandmaker .Quest.storeInBundle( quests );
|
||||
Blacksmith .Quest.storeInBundle( quests );
|
||||
Imp .Quest.storeInBundle( quests );
|
||||
bundle.put( QUESTS, quests );
|
||||
|
||||
Room.storeRoomsInBundle( bundle );
|
||||
|
||||
Statistics.storeInBundle( bundle );
|
||||
Journal.storeInBundle( bundle );
|
||||
|
||||
if (quickslot instanceof Class) {
|
||||
bundle.put( QUICKSLOT, ((Class<?>)quickslot).getName() );
|
||||
}
|
||||
|
||||
Scroll.save( bundle );
|
||||
Potion.save( bundle );
|
||||
Wand.save( bundle );
|
||||
Ring.save( bundle );
|
||||
|
||||
Bundle badges = new Bundle();
|
||||
Badges.saveLocal( badges );
|
||||
bundle.put( BADGES, badges );
|
||||
|
||||
OutputStream output = Game.instance.openFileOutput( fileName, Game.MODE_PRIVATE );
|
||||
Bundle.write( bundle, output );
|
||||
output.close();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
GamesInProgress.setUnknown( hero.heroClass );
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveLevel() throws IOException {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.put( LEVEL, level );
|
||||
|
||||
OutputStream output = Game.instance.openFileOutput(
|
||||
Utils.format( depthFile( hero.heroClass ), depth ), Game.MODE_PRIVATE );
|
||||
Bundle.write( bundle, output );
|
||||
output.close();
|
||||
}
|
||||
|
||||
public static void saveAll() throws IOException {
|
||||
if (hero.isAlive()) {
|
||||
|
||||
Actor.fixTime();
|
||||
saveGame( gameFile( hero.heroClass ) );
|
||||
saveLevel();
|
||||
|
||||
GamesInProgress.set(
|
||||
hero.heroClass,
|
||||
depth,
|
||||
hero.lvl,
|
||||
hero.belongings.armor != null ? hero.belongings.armor.tier : 0 );
|
||||
|
||||
} else if (WndResurrect.instance != null) {
|
||||
|
||||
WndResurrect.instance.hide();
|
||||
Hero.reallyDie( WndResurrect.causeOfDeath );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadGame( HeroClass cl ) throws IOException {
|
||||
loadGame( gameFile( cl ), true );
|
||||
}
|
||||
|
||||
public static void loadGame( String fileName ) throws IOException {
|
||||
loadGame( fileName, false );
|
||||
}
|
||||
|
||||
public static void loadGame( String fileName, boolean fullLoad ) throws IOException {
|
||||
|
||||
Bundle bundle = gameBundle( fileName );
|
||||
|
||||
Dungeon.level = null;
|
||||
Dungeon.depth = -1;
|
||||
|
||||
if (fullLoad) {
|
||||
PathFinder.setMapSize( Level.WIDTH, Level.HEIGHT );
|
||||
}
|
||||
|
||||
Scroll.restore( bundle );
|
||||
Potion.restore( bundle );
|
||||
Wand.restore( bundle );
|
||||
Ring.restore( bundle );
|
||||
|
||||
potionOfStrength = bundle.getInt( POS );
|
||||
scrollsOfUpgrade = bundle.getInt( SOU );
|
||||
arcaneStyli = bundle.getInt( AS );
|
||||
dewVial = bundle.getBoolean( DV );
|
||||
transmutation = bundle.getInt( WT );
|
||||
|
||||
if (fullLoad) {
|
||||
chapters = new HashSet<Integer>();
|
||||
int ids[] = bundle.getIntArray( CHAPTERS );
|
||||
if (ids != null) {
|
||||
for (int id : ids) {
|
||||
chapters.add( id );
|
||||
}
|
||||
}
|
||||
|
||||
Bundle quests = bundle.getBundle( QUESTS );
|
||||
if (!quests.isNull()) {
|
||||
Ghost.Quest.restoreFromBundle( quests );
|
||||
Wandmaker.Quest.restoreFromBundle( quests );
|
||||
Blacksmith.Quest.restoreFromBundle( quests );
|
||||
Imp.Quest.restoreFromBundle( quests );
|
||||
} else {
|
||||
Ghost.Quest.reset();
|
||||
Wandmaker.Quest.reset();
|
||||
Blacksmith.Quest.reset();
|
||||
Imp.Quest.reset();
|
||||
}
|
||||
|
||||
Room.restoreRoomsFromBundle( bundle );
|
||||
}
|
||||
|
||||
Bundle badges = bundle.getBundle( BADGES );
|
||||
if (!badges.isNull()) {
|
||||
Badges.loadLocal( badges );
|
||||
} else {
|
||||
Badges.reset();
|
||||
}
|
||||
|
||||
String qsClass = bundle.getString( QUICKSLOT );
|
||||
if (qsClass != null) {
|
||||
try {
|
||||
quickslot = Class.forName( qsClass );
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
} else {
|
||||
quickslot = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
String version = bundle.getString( VERSION );
|
||||
|
||||
hero = null;
|
||||
hero = (Hero)bundle.get( HERO );
|
||||
|
||||
gold = bundle.getInt( GOLD );
|
||||
depth = bundle.getInt( DEPTH );
|
||||
|
||||
Statistics.restoreFromBundle( bundle );
|
||||
Journal.restoreFromBundle( bundle );
|
||||
}
|
||||
|
||||
public static Level loadLevel( HeroClass cl ) throws IOException {
|
||||
|
||||
Dungeon.level = null;
|
||||
Actor.clear();
|
||||
|
||||
InputStream input = Game.instance.openFileInput( Utils.format( depthFile( cl ), depth ) ) ;
|
||||
Bundle bundle = Bundle.read( input );
|
||||
input.close();
|
||||
|
||||
return (Level)bundle.get( "level" );
|
||||
}
|
||||
|
||||
public static void deleteGame( HeroClass cl, boolean deleteLevels ) {
|
||||
|
||||
Game.instance.deleteFile( gameFile( cl ) );
|
||||
|
||||
if (deleteLevels) {
|
||||
int depth = 1;
|
||||
while (Game.instance.deleteFile( Utils.format( depthFile( cl ), depth ) )) {
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
|
||||
GamesInProgress.delete( cl );
|
||||
}
|
||||
|
||||
public static Bundle gameBundle( String fileName ) throws IOException {
|
||||
|
||||
InputStream input = Game.instance.openFileInput( fileName );
|
||||
Bundle bundle = Bundle.read( input );
|
||||
input.close();
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public static void preview( GamesInProgress.Info info, Bundle bundle ) {
|
||||
info.depth = bundle.getInt( DEPTH );
|
||||
if (info.depth == -1) {
|
||||
info.depth = bundle.getInt( "maxDepth" ); // <-- It has to be refactored!
|
||||
}
|
||||
Hero.preview( info, bundle.getBundle( HERO ) );
|
||||
}
|
||||
|
||||
public static void fail( String desc ) {
|
||||
resultDescription = desc;
|
||||
if (hero.belongings.getItem( Ankh.class ) == null) {
|
||||
Rankings.INSTANCE.submit( false );
|
||||
}
|
||||
}
|
||||
|
||||
public static void win( String desc ) {
|
||||
resultDescription = desc;
|
||||
Rankings.INSTANCE.submit( true );
|
||||
}
|
||||
|
||||
public static void observe() {
|
||||
|
||||
if (level == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
level.updateFieldOfView( hero );
|
||||
System.arraycopy( Level.fieldOfView, 0, visible, 0, visible.length );
|
||||
|
||||
BArray.or( level.visited, visible, level.visited );
|
||||
|
||||
GameScene.afterObserve();
|
||||
}
|
||||
|
||||
private static boolean[] passable = new boolean[Level.LENGTH];
|
||||
|
||||
public static int findPath( Char ch, int from, int to, boolean pass[], boolean[] visible ) {
|
||||
|
||||
if (Level.adjacent( from, to )) {
|
||||
return Actor.findChar( to ) == null && (pass[to] || Level.avoid[to]) ? to : -1;
|
||||
}
|
||||
|
||||
if (ch.flying || ch.buff( Amok.class ) != null) {
|
||||
BArray.or( pass, Level.avoid, passable );
|
||||
} else {
|
||||
System.arraycopy( pass, 0, passable, 0, Level.LENGTH );
|
||||
}
|
||||
|
||||
for (Actor actor : Actor.all()) {
|
||||
if (actor instanceof Char) {
|
||||
int pos = ((Char)actor).pos;
|
||||
if (visible[pos]) {
|
||||
passable[pos] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PathFinder.getStep( from, to, passable );
|
||||
|
||||
}
|
||||
|
||||
public static int flee( Char ch, int cur, int from, boolean pass[], boolean[] visible ) {
|
||||
|
||||
if (ch.flying) {
|
||||
BArray.or( pass, Level.avoid, passable );
|
||||
} else {
|
||||
System.arraycopy( pass, 0, passable, 0, Level.LENGTH );
|
||||
}
|
||||
|
||||
for (Actor actor : Actor.all()) {
|
||||
if (actor instanceof Char) {
|
||||
int pos = ((Char)actor).pos;
|
||||
if (visible[pos]) {
|
||||
passable[pos] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
passable[cur] = true;
|
||||
|
||||
return PathFinder.getStepBack( cur, from, passable );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Image;
|
||||
import com.watabou.noosa.TextureFilm;
|
||||
import com.watabou.noosa.Tilemap;
|
||||
import com.watabou.noosa.tweeners.AlphaTweener;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.PointF;
|
||||
|
||||
public class DungeonTilemap extends Tilemap {
|
||||
|
||||
public static final int SIZE = 16;
|
||||
|
||||
private static DungeonTilemap instance;
|
||||
|
||||
public DungeonTilemap() {
|
||||
super(
|
||||
Dungeon.level.tilesTex(),
|
||||
new TextureFilm( Dungeon.level.tilesTex(), SIZE, SIZE ) );
|
||||
map( Dungeon.level.map, Level.WIDTH );
|
||||
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public int screenToTile( int x, int y ) {
|
||||
Point p = camera().screenToCamera( x, y ).
|
||||
offset( this.point().negate() ).
|
||||
invScale( SIZE ).
|
||||
floor();
|
||||
return p.x >= 0 && p.x < Level.WIDTH && p.y >= 0 && p.y < Level.HEIGHT ? p.x + p.y * Level.WIDTH : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overlapsPoint( float x, float y ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void discover( int pos, int oldValue ) {
|
||||
|
||||
final Image tile = tile( oldValue );
|
||||
tile.point( tileToWorld( pos ) );
|
||||
|
||||
// For bright mode
|
||||
tile.rm = tile.gm = tile.bm = rm;
|
||||
tile.ra = tile.ga = tile.ba = ra;
|
||||
parent.add( tile );
|
||||
|
||||
parent.add( new AlphaTweener( tile, 0, 0.6f ) {
|
||||
protected void onComplete() {
|
||||
tile.killAndErase();
|
||||
killAndErase();
|
||||
};
|
||||
} );
|
||||
}
|
||||
|
||||
public static PointF tileToWorld( int pos ) {
|
||||
return new PointF( pos % Level.WIDTH, pos / Level.WIDTH ).scale( SIZE );
|
||||
}
|
||||
|
||||
public static PointF tileCenterToWorld( int pos ) {
|
||||
return new PointF(
|
||||
(pos % Level.WIDTH + 0.5f) * SIZE,
|
||||
(pos / Level.WIDTH + 0.5f) * SIZE );
|
||||
}
|
||||
|
||||
public static Image tile( int index ) {
|
||||
Image img = new Image( instance.texture );
|
||||
img.frame( instance.tileset.get( index ) );
|
||||
return img;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overlapsScreenPoint( int x, int y ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import com.watabou.gltextures.SmartTexture;
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
import com.watabou.glwrap.Texture;
|
||||
import com.watabou.noosa.Image;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
|
||||
public class FogOfWar extends Image {
|
||||
|
||||
private static final int VISIBLE = 0x00000000;
|
||||
private static final int VISITED = 0xcc111111;
|
||||
private static final int MAPPED = 0xcc442211;
|
||||
private static final int INVISIBLE = 0xFF000000;
|
||||
|
||||
private int[] pixels;
|
||||
|
||||
private int pWidth;
|
||||
private int pHeight;
|
||||
|
||||
private int width2;
|
||||
private int height2;
|
||||
|
||||
public FogOfWar( int mapWidth, int mapHeight ) {
|
||||
|
||||
super();
|
||||
|
||||
pWidth = mapWidth + 1;
|
||||
pHeight = mapHeight + 1;
|
||||
|
||||
width2 = 1;
|
||||
while (width2 < pWidth) {
|
||||
width2 <<= 1;
|
||||
}
|
||||
|
||||
height2 = 1;
|
||||
while (height2 < pHeight) {
|
||||
height2 <<= 1;
|
||||
}
|
||||
|
||||
float size = DungeonTilemap.SIZE;
|
||||
width = width2 * size;
|
||||
height = height2 * size;
|
||||
|
||||
texture( new FogTexture() );
|
||||
|
||||
scale.set(
|
||||
DungeonTilemap.SIZE,
|
||||
DungeonTilemap.SIZE );
|
||||
|
||||
x = y = -size / 2;
|
||||
}
|
||||
|
||||
public void updateVisibility( boolean[] visible, boolean[] visited, boolean[] mapped ) {
|
||||
|
||||
if (pixels == null) {
|
||||
pixels = new int[width2 * height2];
|
||||
Arrays.fill( pixels, INVISIBLE );
|
||||
}
|
||||
|
||||
for (int i=1; i < pHeight - 1; i++) {
|
||||
int pos = (pWidth - 1) * i;
|
||||
for (int j=1; j < pWidth - 1; j++) {
|
||||
pos++;
|
||||
int c = INVISIBLE;
|
||||
if (visible[pos] && visible[pos - (pWidth - 1)] &&
|
||||
visible[pos - 1] && visible[pos - (pWidth - 1) - 1]) {
|
||||
c = VISIBLE;
|
||||
} else
|
||||
if (visited[pos] && visited[pos - (pWidth - 1)] &&
|
||||
visited[pos - 1] && visited[pos - (pWidth - 1) - 1]) {
|
||||
c = VISITED;
|
||||
}
|
||||
else
|
||||
if (mapped[pos] && mapped[pos - (pWidth - 1)] &&
|
||||
mapped[pos - 1] && mapped[pos - (pWidth - 1) - 1]) {
|
||||
c = MAPPED;
|
||||
}
|
||||
pixels[i * width2 + j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
texture.pixels( width2, height2, pixels );
|
||||
}
|
||||
|
||||
private class FogTexture extends SmartTexture {
|
||||
|
||||
public FogTexture() {
|
||||
super( Bitmap.createBitmap( width2, height2, Bitmap.Config.ARGB_8888 ) );
|
||||
filter( Texture.LINEAR, Texture.LINEAR );
|
||||
TextureCache.add( FogOfWar.class, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
GameScene.afterObserve();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class GamesInProgress {
|
||||
|
||||
private static HashMap<HeroClass, Info> state = new HashMap<HeroClass, Info>();
|
||||
|
||||
public static Info check( HeroClass cl ) {
|
||||
|
||||
if (state.containsKey( cl )) {
|
||||
|
||||
return state.get( cl );
|
||||
|
||||
} else {
|
||||
|
||||
Info info;
|
||||
try {
|
||||
|
||||
Bundle bundle = Dungeon.gameBundle( Dungeon.gameFile( cl ) );
|
||||
info = new Info();
|
||||
Dungeon.preview( info, bundle );
|
||||
|
||||
} catch (Exception e) {
|
||||
info = null;
|
||||
}
|
||||
|
||||
state.put( cl, info );
|
||||
return info;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void set( HeroClass cl, int depth, int level, int armor ) {
|
||||
Info info = new Info();
|
||||
info.depth = depth;
|
||||
info.level = level;
|
||||
info.armor = armor;
|
||||
state.put( cl, info );
|
||||
}
|
||||
|
||||
public static void setUnknown( HeroClass cl ) {
|
||||
state.remove( cl );
|
||||
}
|
||||
|
||||
public static void delete( HeroClass cl ) {
|
||||
state.put( cl, null );
|
||||
}
|
||||
|
||||
public static class Info {
|
||||
public int depth;
|
||||
public int level;
|
||||
public int armor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.watabou.utils.Bundlable;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class Journal {
|
||||
|
||||
public static enum Feature {
|
||||
WELL_OF_HEALTH ( "Well of Health" ),
|
||||
WELL_OF_AWARENESS ( "Well of Awareness" ),
|
||||
WELL_OF_TRANSMUTATION ( "Well of Transmutation" ),
|
||||
ALCHEMY ( "Alchemy pot" ),
|
||||
GARDEN ( "Garden" ),
|
||||
STATUE ( "Animated statue" ),
|
||||
|
||||
GHOST ( "Sad ghost" ),
|
||||
WANDMAKER ( "Old wandmaker" ),
|
||||
TROLL ( "Troll blacksmith" ),
|
||||
IMP ( "Ambitious imp" );
|
||||
|
||||
public String desc;
|
||||
|
||||
private Feature( String desc ) {
|
||||
this.desc = desc;
|
||||
}
|
||||
};
|
||||
|
||||
public static class Record implements Comparable<Record>, Bundlable {
|
||||
|
||||
private static final String FEATURE = "feature";
|
||||
private static final String DEPTH = "depth";
|
||||
|
||||
public Feature feature;
|
||||
public int depth;
|
||||
|
||||
public Record() {
|
||||
}
|
||||
|
||||
public Record( Feature feature, int depth ) {
|
||||
this.feature = feature;
|
||||
this.depth = depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo( Record another ) {
|
||||
return another.depth - depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
feature = Feature.valueOf( bundle.getString( FEATURE ) );
|
||||
depth = bundle.getInt( DEPTH );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( FEATURE, feature.toString() );
|
||||
bundle.put( DEPTH, depth );
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<Record> records;
|
||||
|
||||
public static void reset() {
|
||||
records = new ArrayList<Journal.Record>();
|
||||
}
|
||||
|
||||
private static final String JOURNAL = "journal";
|
||||
|
||||
public static void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( JOURNAL, records );
|
||||
}
|
||||
|
||||
public static void restoreFromBundle( Bundle bundle ) {
|
||||
records = new ArrayList<Record>();
|
||||
for (Bundlable rec : bundle.getCollection( JOURNAL ) ) {
|
||||
records.add( (Record) rec );
|
||||
}
|
||||
}
|
||||
|
||||
public static void add( Feature feature ) {
|
||||
int size = records.size();
|
||||
for (int i=0; i < size; i++) {
|
||||
Record rec = records.get( i );
|
||||
if (rec.feature == feature && rec.depth == Dungeon.depth) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
records.add( new Record( feature, Dungeon.depth ) );
|
||||
}
|
||||
|
||||
public static void remove( Feature feature ) {
|
||||
int size = records.size();
|
||||
for (int i=0; i < size; i++) {
|
||||
Record rec = records.get( i );
|
||||
if (rec.feature == feature && rec.depth == Dungeon.depth) {
|
||||
records.remove( i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
enum Preferences {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public static final String KEY_LANDSCAPE = "landscape";
|
||||
public static final String KEY_SCALE_UP = "scaleup";
|
||||
public static final String KEY_MUSIC = "music";
|
||||
public static final String KEY_SOUND_FX = "soundfx";
|
||||
public static final String KEY_ZOOM = "zoom";
|
||||
public static final String KEY_LAST_CLASS = "last_class";
|
||||
public static final String KEY_DONATED = "donated";
|
||||
public static final String KEY_INTRO = "intro";
|
||||
public static final String KEY_BRIGHTNESS = "brightness";
|
||||
|
||||
private SharedPreferences prefs;
|
||||
|
||||
private SharedPreferences get() {
|
||||
if (prefs == null) {
|
||||
prefs = Game.instance.getPreferences( Game.MODE_PRIVATE );
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
int getInt( String key, int defValue ) {
|
||||
return get().getInt( key, defValue );
|
||||
}
|
||||
|
||||
boolean getBoolean( String key, boolean defValue ) {
|
||||
return get().getBoolean( key, defValue );
|
||||
}
|
||||
|
||||
String getString( String key, String defValue ) {
|
||||
return get().getString( key, defValue );
|
||||
}
|
||||
|
||||
void put( String key, int value ) {
|
||||
get().edit().putInt( key, value ).commit();
|
||||
}
|
||||
|
||||
void put( String key, boolean value ) {
|
||||
get().edit().putBoolean( key, value ).commit();
|
||||
}
|
||||
|
||||
void put( String key, String value ) {
|
||||
get().edit().putString( key, value ).commit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Bundlable;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.SystemTime;
|
||||
|
||||
public enum Rankings {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public static final int TABLE_SIZE = 6;
|
||||
|
||||
public static final String RANKINGS_FILE = "rankings.dat";
|
||||
public static final String DETAILS_FILE = "game_%d.dat";
|
||||
|
||||
public ArrayList<Record> records;
|
||||
public int lastRecord;
|
||||
public int totalNumber;
|
||||
|
||||
public void submit( boolean win ) {
|
||||
|
||||
load();
|
||||
|
||||
Record rec = new Record();
|
||||
|
||||
rec.info = Dungeon.resultDescription;
|
||||
rec.win = win;
|
||||
rec.heroClass = Dungeon.hero.heroClass;
|
||||
rec.armorTier = Dungeon.hero.tier();
|
||||
rec.score = score( win );
|
||||
|
||||
String gameFile = Utils.format( DETAILS_FILE, SystemTime.now );
|
||||
try {
|
||||
Dungeon.saveGame( gameFile );
|
||||
rec.gameFile = gameFile;
|
||||
} catch (IOException e) {
|
||||
rec.gameFile = "";
|
||||
}
|
||||
|
||||
records.add( rec );
|
||||
|
||||
Collections.sort( records, scoreComparator );
|
||||
|
||||
lastRecord = records.indexOf( rec );
|
||||
int size = records.size();
|
||||
if (size > TABLE_SIZE) {
|
||||
|
||||
Record removedGame;
|
||||
if (lastRecord == size - 1) {
|
||||
removedGame = records.remove( size - 2 );
|
||||
lastRecord--;
|
||||
} else {
|
||||
removedGame = records.remove( size - 1 );
|
||||
}
|
||||
|
||||
if (removedGame.gameFile.length() > 0) {
|
||||
Game.instance.deleteFile( removedGame.gameFile );
|
||||
}
|
||||
}
|
||||
|
||||
totalNumber++;
|
||||
|
||||
Badges.validateGamesPlayed();
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
private int score( boolean win ) {
|
||||
return (Statistics.goldCollected + Dungeon.hero.lvl * Dungeon.depth * 100) * (win ? 2 : 1);
|
||||
}
|
||||
|
||||
private static final String RECORDS = "records";
|
||||
private static final String LATEST = "latest";
|
||||
private static final String TOTAL = "total";
|
||||
|
||||
public void save() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.put( RECORDS, records );
|
||||
bundle.put( LATEST, lastRecord );
|
||||
bundle.put( TOTAL, totalNumber );
|
||||
|
||||
try {
|
||||
OutputStream output = Game.instance.openFileOutput( RANKINGS_FILE, Game.MODE_PRIVATE );
|
||||
Bundle.write( bundle, output );
|
||||
output.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void load() {
|
||||
|
||||
if (records != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
records = new ArrayList<Rankings.Record>();
|
||||
|
||||
try {
|
||||
InputStream input = Game.instance.openFileInput( RANKINGS_FILE );
|
||||
Bundle bundle = Bundle.read( input );
|
||||
input.close();
|
||||
|
||||
for (Bundlable record : bundle.getCollection( RECORDS )) {
|
||||
records.add( (Record)record );
|
||||
}
|
||||
lastRecord = bundle.getInt( LATEST );
|
||||
|
||||
totalNumber = bundle.getInt( TOTAL );
|
||||
if (totalNumber == 0) {
|
||||
totalNumber = records.size();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public static class Record implements Bundlable {
|
||||
|
||||
private static final String REASON = "reason";
|
||||
private static final String WIN = "win";
|
||||
private static final String SCORE = "score";
|
||||
private static final String TIER = "tier";
|
||||
private static final String GAME = "gameFile";
|
||||
|
||||
public String info;
|
||||
public boolean win;
|
||||
|
||||
public HeroClass heroClass;
|
||||
public int armorTier;
|
||||
|
||||
public int score;
|
||||
|
||||
public String gameFile;
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
info = bundle.getString( REASON );
|
||||
win = bundle.getBoolean( WIN );
|
||||
score = bundle.getInt( SCORE );
|
||||
|
||||
heroClass = HeroClass.restoreInBundle( bundle );
|
||||
armorTier = bundle.getInt( TIER );
|
||||
|
||||
gameFile = bundle.getString( GAME );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
|
||||
bundle.put( REASON, info );
|
||||
bundle.put( WIN, win );
|
||||
bundle.put( SCORE, score );
|
||||
|
||||
heroClass.storeInBundle( bundle );
|
||||
bundle.put( TIER, armorTier );
|
||||
|
||||
bundle.put( GAME, gameFile );
|
||||
}
|
||||
}
|
||||
|
||||
private static final Comparator<Record> scoreComparator = new Comparator<Rankings.Record>() {
|
||||
@Override
|
||||
public int compare( Record lhs, Record rhs ) {
|
||||
return (int)Math.signum( rhs.score - lhs.score );
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class ResultDescriptions {
|
||||
|
||||
// Mobs
|
||||
public static final String MOB = "Killed by %s on level %d";
|
||||
public static final String BOSS = "Killed by the %s on level %d";
|
||||
|
||||
// Items
|
||||
public static final String WAND = "Killed by your own %s on level %d";
|
||||
public static final String GLYPH = "Killed by the %s on level %d";
|
||||
|
||||
// Dungeon features
|
||||
public static final String TRAP = "Killed by discharge of %s on level %d";
|
||||
|
||||
// Debuffs & blobs
|
||||
public static final String BURNING = "Burned to death on level %d";
|
||||
public static final String HUNGER = "Starved to death on level %d";
|
||||
public static final String POISON = "Died from poison on level %d";
|
||||
public static final String GAS = "Died from toxic gas on level %d";
|
||||
public static final String BLEEDING = "Bled to death on level %d";
|
||||
public static final String OOZE = "Killed by a caustic ooze on level %d";
|
||||
public static final String FALL = "Fell to death on level %d";
|
||||
|
||||
public static final String WIN = "Obtained the Amulet of Yendor";
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.audio.Music;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.TitleScene;
|
||||
|
||||
public class ShatteredPixelDungeon extends Game {
|
||||
|
||||
public ShatteredPixelDungeon() {
|
||||
super( TitleScene.class );
|
||||
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfEnhancement" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfHealth.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Light" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfMending.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfRejuvenation" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfTelekinesis.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfTelekenesis" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Foliage.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blooming" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Shadows.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Rejuvenation" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfNuclearBlast" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.actors.Hero" );
|
||||
// com.watabou.utils.Bundle.addAlias(
|
||||
// com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Javelin.class,
|
||||
// "com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Boomerang" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Shopkeeper" );
|
||||
// 1.6.1
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.quest.DriedRose.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.DriedRose" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.MirrorImage.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMirrorImage.MirrorImage" );
|
||||
// 1.6.4
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfCleansing" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfResistance" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Boomerang.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.RangersBoomerang" );
|
||||
com.watabou.utils.Bundle.addAlias(
|
||||
com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfPower.class,
|
||||
"com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEnergy" );
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onCreate( Bundle savedInstanceState ) {
|
||||
super.onCreate( savedInstanceState );
|
||||
|
||||
/* if (android.os.Build.VERSION.SDK_INT >= 19) {
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY );
|
||||
}*/
|
||||
|
||||
Display display = instance.getWindowManager().getDefaultDisplay();
|
||||
boolean landscape = display.getWidth() > display.getHeight();
|
||||
|
||||
if (Preferences.INSTANCE.getBoolean( Preferences.KEY_LANDSCAPE, false ) != landscape) {
|
||||
landscape( !landscape );
|
||||
}
|
||||
|
||||
Music.INSTANCE.enable( music() );
|
||||
Sample.INSTANCE.enable( soundFx() );
|
||||
}
|
||||
|
||||
/*
|
||||
* ---> Prefernces
|
||||
*/
|
||||
|
||||
public static void landscape( boolean value ) {
|
||||
Game.instance.setRequestedOrientation( value ?
|
||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE :
|
||||
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT );
|
||||
Preferences.INSTANCE.put( Preferences.KEY_LANDSCAPE, value );
|
||||
}
|
||||
|
||||
public static boolean landscape() {
|
||||
return width > height;
|
||||
}
|
||||
|
||||
public static void scaleUp( boolean value ) {
|
||||
Preferences.INSTANCE.put( Preferences.KEY_SCALE_UP, value );
|
||||
switchScene( TitleScene.class );
|
||||
}
|
||||
|
||||
public static boolean scaleUp() {
|
||||
return Preferences.INSTANCE.getBoolean( Preferences.KEY_SCALE_UP, true );
|
||||
}
|
||||
|
||||
public static void zoom( int value ) {
|
||||
Preferences.INSTANCE.put( Preferences.KEY_ZOOM, value );
|
||||
}
|
||||
|
||||
public static int zoom() {
|
||||
return Preferences.INSTANCE.getInt( Preferences.KEY_ZOOM, 0 );
|
||||
}
|
||||
|
||||
public static void music( boolean value ) {
|
||||
Music.INSTANCE.enable( value );
|
||||
Preferences.INSTANCE.put( Preferences.KEY_MUSIC, value );
|
||||
}
|
||||
|
||||
public static boolean music() {
|
||||
return Preferences.INSTANCE.getBoolean( Preferences.KEY_MUSIC, true );
|
||||
}
|
||||
|
||||
public static void soundFx( boolean value ) {
|
||||
Sample.INSTANCE.enable( value );
|
||||
Preferences.INSTANCE.put( Preferences.KEY_SOUND_FX, value );
|
||||
}
|
||||
|
||||
public static boolean soundFx() {
|
||||
return Preferences.INSTANCE.getBoolean( Preferences.KEY_SOUND_FX, true );
|
||||
}
|
||||
|
||||
public static void brightness( boolean value ) {
|
||||
Preferences.INSTANCE.put( Preferences.KEY_BRIGHTNESS, value );
|
||||
if (scene() instanceof GameScene) {
|
||||
((GameScene)scene()).brightness( value );
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean brightness() {
|
||||
return Preferences.INSTANCE.getBoolean( Preferences.KEY_BRIGHTNESS, false );
|
||||
}
|
||||
|
||||
public static void donated( String value ) {
|
||||
Preferences.INSTANCE.put( Preferences.KEY_DONATED, value );
|
||||
}
|
||||
|
||||
public static String donated() {
|
||||
return Preferences.INSTANCE.getString( Preferences.KEY_DONATED, "" );
|
||||
}
|
||||
|
||||
public static void lastClass( int value ) {
|
||||
Preferences.INSTANCE.put( Preferences.KEY_LAST_CLASS, value );
|
||||
}
|
||||
|
||||
public static int lastClass() {
|
||||
return Preferences.INSTANCE.getInt( Preferences.KEY_LAST_CLASS, 0 );
|
||||
}
|
||||
|
||||
public static void intro( boolean value ) {
|
||||
Preferences.INSTANCE.put( Preferences.KEY_INTRO, value );
|
||||
}
|
||||
|
||||
public static boolean intro() {
|
||||
return Preferences.INSTANCE.getBoolean( Preferences.KEY_INTRO, true );
|
||||
}
|
||||
|
||||
/*
|
||||
* <--- Preferences
|
||||
*/
|
||||
|
||||
public static void reportException( Exception e ) {
|
||||
Log.e( "PD", Log.getStackTraceString( e ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class Statistics {
|
||||
|
||||
public static int goldCollected;
|
||||
public static int deepestFloor;
|
||||
public static int enemiesSlain;
|
||||
public static int foodEaten;
|
||||
public static int potionsCooked;
|
||||
public static int piranhasKilled;
|
||||
public static int nightHunt;
|
||||
public static int ankhsUsed;
|
||||
|
||||
public static float duration;
|
||||
|
||||
public static boolean qualifiedForNoKilling = false;
|
||||
public static boolean completedWithNoKilling = false;
|
||||
|
||||
public static boolean amuletObtained = false;
|
||||
|
||||
public static void reset() {
|
||||
|
||||
goldCollected = 0;
|
||||
deepestFloor = 0;
|
||||
enemiesSlain = 0;
|
||||
foodEaten = 0;
|
||||
potionsCooked = 0;
|
||||
piranhasKilled = 0;
|
||||
nightHunt = 0;
|
||||
ankhsUsed = 0;
|
||||
|
||||
duration = 0;
|
||||
|
||||
qualifiedForNoKilling = false;
|
||||
|
||||
amuletObtained = false;
|
||||
|
||||
}
|
||||
|
||||
private static final String GOLD = "score";
|
||||
private static final String DEEPEST = "maxDepth";
|
||||
private static final String SLAIN = "enemiesSlain";
|
||||
private static final String FOOD = "foodEaten";
|
||||
private static final String ALCHEMY = "potionsCooked";
|
||||
private static final String PIRANHAS = "priranhas";
|
||||
private static final String NIGHT = "nightHunt";
|
||||
private static final String ANKHS = "ankhsUsed";
|
||||
private static final String DURATION = "duration";
|
||||
private static final String AMULET = "amuletObtained";
|
||||
|
||||
public static void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( GOLD, goldCollected );
|
||||
bundle.put( DEEPEST, deepestFloor );
|
||||
bundle.put( SLAIN, enemiesSlain );
|
||||
bundle.put( FOOD, foodEaten );
|
||||
bundle.put( ALCHEMY, potionsCooked );
|
||||
bundle.put( PIRANHAS, piranhasKilled );
|
||||
bundle.put( NIGHT, nightHunt );
|
||||
bundle.put( ANKHS, ankhsUsed );
|
||||
bundle.put( DURATION, duration );
|
||||
bundle.put( AMULET, amuletObtained );
|
||||
}
|
||||
|
||||
public static void restoreFromBundle( Bundle bundle ) {
|
||||
goldCollected = bundle.getInt( GOLD );
|
||||
deepestFloor = bundle.getInt( DEEPEST );
|
||||
enemiesSlain = bundle.getInt( SLAIN );
|
||||
foodEaten = bundle.getInt( FOOD );
|
||||
potionsCooked = bundle.getInt( ALCHEMY );
|
||||
piranhasKilled = bundle.getInt( PIRANHAS );
|
||||
nightHunt = bundle.getInt( NIGHT );
|
||||
ankhsUsed = bundle.getInt( ANKHS );
|
||||
duration = bundle.getFloat( DURATION );
|
||||
amuletObtained = bundle.getBoolean( AMULET );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.watabou.utils.Bundlable;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public abstract class Actor implements Bundlable {
|
||||
|
||||
public static final float TICK = 1f;
|
||||
|
||||
private float time;
|
||||
|
||||
protected abstract boolean act();
|
||||
|
||||
protected void spend( float time ) {
|
||||
this.time += time;
|
||||
}
|
||||
|
||||
protected void postpone( float time ) {
|
||||
if (this.time < now + time) {
|
||||
this.time = now + time;
|
||||
}
|
||||
}
|
||||
|
||||
protected float cooldown() {
|
||||
return time - now;
|
||||
}
|
||||
|
||||
protected void diactivate() {
|
||||
time = Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
protected void onAdd() {}
|
||||
|
||||
protected void onRemove() {}
|
||||
|
||||
private static final String TIME = "time";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( TIME, time );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
time = bundle.getFloat( TIME );
|
||||
}
|
||||
|
||||
// **********************
|
||||
// *** Static members ***
|
||||
|
||||
private static HashSet<Actor> all = new HashSet<Actor>();
|
||||
private static Actor current;
|
||||
|
||||
private static float now = 0;
|
||||
|
||||
private static Char[] chars = new Char[Level.LENGTH];
|
||||
|
||||
public static void clear() {
|
||||
|
||||
now = 0;
|
||||
|
||||
Arrays.fill( chars, null );
|
||||
all.clear();
|
||||
}
|
||||
|
||||
public static void fixTime() {
|
||||
|
||||
if (Dungeon.hero != null && all.contains( Dungeon.hero )) {
|
||||
Statistics.duration += now;
|
||||
}
|
||||
|
||||
float min = Float.MAX_VALUE;
|
||||
for (Actor a : all) {
|
||||
if (a.time < min) {
|
||||
min = a.time;
|
||||
}
|
||||
}
|
||||
for (Actor a : all) {
|
||||
a.time -= min;
|
||||
}
|
||||
now = 0;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
||||
addDelayed( Dungeon.hero, -Float.MIN_VALUE );
|
||||
|
||||
for (Mob mob : Dungeon.level.mobs) {
|
||||
add( mob );
|
||||
}
|
||||
|
||||
for (Blob blob : Dungeon.level.blobs.values()) {
|
||||
add( blob );
|
||||
}
|
||||
|
||||
current = null;
|
||||
}
|
||||
|
||||
public static void occupyCell( Char ch ) {
|
||||
chars[ch.pos] = ch;
|
||||
}
|
||||
|
||||
public static void freeCell( int pos ) {
|
||||
chars[pos] = null;
|
||||
}
|
||||
|
||||
protected static void next() {
|
||||
current = null;
|
||||
}
|
||||
|
||||
public static void process() {
|
||||
|
||||
if (current != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean doNext;
|
||||
|
||||
do {
|
||||
now = Float.MAX_VALUE;
|
||||
current = null;
|
||||
|
||||
Arrays.fill( chars, null );
|
||||
|
||||
for (Actor actor : all) {
|
||||
if (actor.time < now) {
|
||||
now = actor.time;
|
||||
current = actor;
|
||||
}
|
||||
|
||||
if (actor instanceof Char) {
|
||||
Char ch = (Char)actor;
|
||||
chars[ch.pos] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (current != null) {
|
||||
doNext = current.act();
|
||||
if (doNext && !Dungeon.hero.isAlive()) {
|
||||
doNext = false;
|
||||
current = null;
|
||||
}
|
||||
} else {
|
||||
doNext = false;
|
||||
}
|
||||
|
||||
} while (doNext);
|
||||
}
|
||||
|
||||
public static void add( Actor actor ) {
|
||||
add( actor, now );
|
||||
}
|
||||
|
||||
public static void addDelayed( Actor actor, float delay ) {
|
||||
add( actor, now + delay );
|
||||
}
|
||||
|
||||
private static void add( Actor actor, float time ) {
|
||||
|
||||
if (all.contains( actor )) {
|
||||
return;
|
||||
}
|
||||
|
||||
all.add( actor );
|
||||
actor.time += time; // (+=) => (=) ?
|
||||
actor.onAdd();
|
||||
|
||||
if (actor instanceof Char) {
|
||||
Char ch = (Char)actor;
|
||||
chars[ch.pos] = ch;
|
||||
for (Buff buff : ch.buffs()) {
|
||||
all.add( buff );
|
||||
buff.onAdd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void remove( Actor actor ) {
|
||||
|
||||
if (actor != null) {
|
||||
all.remove( actor );
|
||||
actor.onRemove();
|
||||
}
|
||||
}
|
||||
|
||||
public static Char findChar( int pos ) {
|
||||
return chars[pos];
|
||||
}
|
||||
|
||||
public static HashSet<Actor> all() {
|
||||
return all;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Invisibility;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Shadows;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Speed;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Levitation;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Slow;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PoisonParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Bundlable;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public abstract class Char extends Actor {
|
||||
|
||||
protected static final String TXT_HIT = "%s hit %s";
|
||||
protected static final String TXT_KILL = "%s killed you...";
|
||||
protected static final String TXT_DEFEAT = "%s defeated %s";
|
||||
|
||||
private static final String TXT_YOU_MISSED = "%s %s your attack";
|
||||
private static final String TXT_SMB_MISSED = "%s %s %s's attack";
|
||||
|
||||
private static final String TXT_OUT_OF_PARALYSIS = "The pain snapped %s out of paralysis";
|
||||
|
||||
public int pos = 0;
|
||||
|
||||
public CharSprite sprite;
|
||||
|
||||
public String name = "mob";
|
||||
|
||||
public int HT;
|
||||
public int HP;
|
||||
|
||||
protected float baseSpeed = 1;
|
||||
|
||||
public boolean paralysed = false;
|
||||
public boolean pacified = false;
|
||||
public boolean rooted = false;
|
||||
public boolean flying = false;
|
||||
public int invisible = 0;
|
||||
|
||||
public int viewDistance = 8;
|
||||
|
||||
private HashSet<Buff> buffs = new HashSet<Buff>();
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
Dungeon.level.updateFieldOfView( this );
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final String POS = "pos";
|
||||
private static final String TAG_HP = "HP";
|
||||
private static final String TAG_HT = "HT";
|
||||
private static final String BUFFS = "buffs";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
|
||||
super.storeInBundle( bundle );
|
||||
|
||||
bundle.put( POS, pos );
|
||||
bundle.put( TAG_HP, HP );
|
||||
bundle.put( TAG_HT, HT );
|
||||
bundle.put( BUFFS, buffs );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
super.restoreFromBundle( bundle );
|
||||
|
||||
pos = bundle.getInt( POS );
|
||||
HP = bundle.getInt( TAG_HP );
|
||||
HT = bundle.getInt( TAG_HT );
|
||||
|
||||
for (Bundlable b : bundle.getCollection( BUFFS )) {
|
||||
if (b != null) {
|
||||
((Buff)b).attachTo( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean attack( Char enemy ) {
|
||||
|
||||
boolean visibleFight = Dungeon.visible[pos] || Dungeon.visible[enemy.pos];
|
||||
|
||||
if (hit( this, enemy, false )) {
|
||||
|
||||
if (visibleFight) {
|
||||
GLog.i( TXT_HIT, name, enemy.name );
|
||||
}
|
||||
|
||||
// Refactoring needed!
|
||||
int dr = this instanceof Hero && ((Hero)this).usingRanged && ((Hero)this).subClass == HeroSubClass.SNIPER ?
|
||||
0 : Random.IntRange( 0, enemy.dr() );
|
||||
|
||||
int dmg = damageRoll();
|
||||
int effectiveDamage = Math.max( dmg - dr, 0 );;
|
||||
|
||||
effectiveDamage = attackProc( enemy, effectiveDamage );
|
||||
effectiveDamage = enemy.defenseProc( this, effectiveDamage );
|
||||
enemy.damage( effectiveDamage, this );
|
||||
|
||||
if (visibleFight) {
|
||||
Sample.INSTANCE.play( Assets.SND_HIT, 1, 1, Random.Float( 0.8f, 1.25f ) );
|
||||
}
|
||||
|
||||
if (enemy == Dungeon.hero) {
|
||||
Dungeon.hero.interrupt();
|
||||
}
|
||||
|
||||
enemy.sprite.bloodBurstA( sprite.center(), effectiveDamage );
|
||||
enemy.sprite.flash();
|
||||
|
||||
if (!enemy.isAlive() && visibleFight) {
|
||||
if (enemy == Dungeon.hero) {
|
||||
|
||||
if (Dungeon.hero.killerGlyph != null) {
|
||||
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.GLYPH, Dungeon.hero.killerGlyph.name(), Dungeon.depth ) );
|
||||
GLog.n( TXT_KILL, Dungeon.hero.killerGlyph.name() );
|
||||
|
||||
} else {
|
||||
if (Bestiary.isUnique( this )) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.BOSS, name, Dungeon.depth ) );
|
||||
} else {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.MOB,
|
||||
Utils.indefinite( name ), Dungeon.depth ) );
|
||||
}
|
||||
|
||||
GLog.n( TXT_KILL, name );
|
||||
}
|
||||
|
||||
} else {
|
||||
GLog.i( TXT_DEFEAT, name, enemy.name );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
if (visibleFight) {
|
||||
String defense = enemy.defenseVerb();
|
||||
enemy.sprite.showStatus( CharSprite.NEUTRAL, defense );
|
||||
if (this == Dungeon.hero) {
|
||||
GLog.i( TXT_YOU_MISSED, enemy.name, defense );
|
||||
} else {
|
||||
GLog.i( TXT_SMB_MISSED, enemy.name, defense, name );
|
||||
}
|
||||
|
||||
Sample.INSTANCE.play( Assets.SND_MISS );
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hit( Char attacker, Char defender, boolean magic ) {
|
||||
float acuRoll = Random.Float( attacker.attackSkill( defender ) );
|
||||
float defRoll = Random.Float( defender.defenseSkill( attacker ) );
|
||||
return (magic ? acuRoll * 2 : acuRoll) >= defRoll;
|
||||
}
|
||||
|
||||
public int attackSkill( Char target ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int defenseSkill( Char enemy ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String defenseVerb() {
|
||||
return "dodged";
|
||||
}
|
||||
|
||||
public int dr() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int damageRoll() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
return damage;
|
||||
}
|
||||
|
||||
public int defenseProc( Char enemy, int damage ) {
|
||||
return damage;
|
||||
}
|
||||
|
||||
public float speed() {
|
||||
return buff( Cripple.class ) == null ? baseSpeed : baseSpeed * 0.5f;
|
||||
}
|
||||
|
||||
public void damage( int dmg, Object src ) {
|
||||
|
||||
if (HP <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Buff.detach( this, Frost.class );
|
||||
|
||||
Class<?> srcClass = src.getClass();
|
||||
if (immunities().contains( srcClass )) {
|
||||
dmg = 0;
|
||||
} else if (resistances().contains( srcClass )) {
|
||||
dmg = Random.IntRange( 0, dmg );
|
||||
}
|
||||
|
||||
if (buff( Paralysis.class ) != null) {
|
||||
if (Random.Int( dmg ) >= Random.Int( HP )) {
|
||||
Buff.detach( this, Paralysis.class );
|
||||
if (Dungeon.visible[pos]) {
|
||||
GLog.i( TXT_OUT_OF_PARALYSIS, name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HP -= dmg;
|
||||
if (dmg > 0 || src instanceof Char) {
|
||||
sprite.showStatus( HP > HT / 2 ?
|
||||
CharSprite.WARNING :
|
||||
CharSprite.NEGATIVE,
|
||||
Integer.toString( dmg ) );
|
||||
}
|
||||
if (HP <= 0) {
|
||||
die( src );
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
HP = 0;
|
||||
Actor.remove( this );
|
||||
Actor.freeCell( pos );
|
||||
}
|
||||
|
||||
public void die( Object src ) {
|
||||
destroy();
|
||||
sprite.die();
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return HP > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void spend( float time ) {
|
||||
|
||||
float timeScale = 1f;
|
||||
if (buff( Slow.class ) != null) {
|
||||
timeScale *= 0.5f;
|
||||
}
|
||||
if (buff( Speed.class ) != null) {
|
||||
timeScale *= 2.0f;
|
||||
}
|
||||
|
||||
super.spend( time / timeScale );
|
||||
}
|
||||
|
||||
public HashSet<Buff> buffs() {
|
||||
return buffs;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Buff> HashSet<T> buffs( Class<T> c ) {
|
||||
HashSet<T> filtered = new HashSet<T>();
|
||||
for (Buff b : buffs) {
|
||||
if (c.isInstance( b )) {
|
||||
filtered.add( (T)b );
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Buff> T buff( Class<T> c ) {
|
||||
for (Buff b : buffs) {
|
||||
if (c.isInstance( b )) {
|
||||
return (T)b;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void add( Buff buff ) {
|
||||
|
||||
buffs.add( buff );
|
||||
Actor.add( buff );
|
||||
|
||||
if (sprite != null) {
|
||||
if (buff instanceof Poison) {
|
||||
|
||||
CellEmitter.center( pos ).burst( PoisonParticle.SPLASH, 5 );
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "poisoned" );
|
||||
|
||||
} else if (buff instanceof Amok) {
|
||||
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "amok" );
|
||||
|
||||
} else if (buff instanceof Slow) {
|
||||
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "slowed" );
|
||||
|
||||
} else if (buff instanceof MindVision) {
|
||||
|
||||
sprite.showStatus( CharSprite.POSITIVE, "mind" );
|
||||
sprite.showStatus( CharSprite.POSITIVE, "vision" );
|
||||
|
||||
} else if (buff instanceof Paralysis) {
|
||||
|
||||
sprite.add( CharSprite.State.PARALYSED );
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "paralysed" );
|
||||
|
||||
} else if (buff instanceof Terror) {
|
||||
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "frightened" );
|
||||
|
||||
} else if (buff instanceof Roots) {
|
||||
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "rooted" );
|
||||
|
||||
} else if (buff instanceof Cripple) {
|
||||
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "crippled" );
|
||||
|
||||
} else if (buff instanceof Bleeding) {
|
||||
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "bleeding" );
|
||||
|
||||
} else if (buff instanceof Sleep) {
|
||||
sprite.idle();
|
||||
}
|
||||
|
||||
else if (buff instanceof Burning) {
|
||||
sprite.add( CharSprite.State.BURNING );
|
||||
} else if (buff instanceof Levitation) {
|
||||
sprite.add( CharSprite.State.LEVITATING );
|
||||
} else if (buff instanceof Frost) {
|
||||
sprite.add( CharSprite.State.FROZEN );
|
||||
} else if (buff instanceof Invisibility) {
|
||||
if (!(buff instanceof Shadows)) {
|
||||
sprite.showStatus( CharSprite.POSITIVE, "invisible" );
|
||||
}
|
||||
sprite.add( CharSprite.State.INVISIBLE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void remove( Buff buff ) {
|
||||
|
||||
buffs.remove( buff );
|
||||
Actor.remove( buff );
|
||||
|
||||
if (buff instanceof Burning) {
|
||||
sprite.remove( CharSprite.State.BURNING );
|
||||
} else if (buff instanceof Levitation) {
|
||||
sprite.remove( CharSprite.State.LEVITATING );
|
||||
} else if (buff instanceof Invisibility && invisible <= 0) {
|
||||
sprite.remove( CharSprite.State.INVISIBLE );
|
||||
} else if (buff instanceof Paralysis) {
|
||||
sprite.remove( CharSprite.State.PARALYSED );
|
||||
} else if (buff instanceof Frost) {
|
||||
sprite.remove( CharSprite.State.FROZEN );
|
||||
}
|
||||
}
|
||||
|
||||
public void remove( Class<? extends Buff> buffClass ) {
|
||||
for (Buff buff : buffs( buffClass )) {
|
||||
remove( buff );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove() {
|
||||
for (Buff buff : buffs.toArray( new Buff[0] )) {
|
||||
buff.detach();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSpriteState() {
|
||||
for (Buff buff:buffs) {
|
||||
if (buff instanceof Burning) {
|
||||
sprite.add( CharSprite.State.BURNING );
|
||||
} else if (buff instanceof Levitation) {
|
||||
sprite.add( CharSprite.State.LEVITATING );
|
||||
} else if (buff instanceof Invisibility) {
|
||||
sprite.add( CharSprite.State.INVISIBLE );
|
||||
} else if (buff instanceof Paralysis) {
|
||||
sprite.add( CharSprite.State.PARALYSED );
|
||||
} else if (buff instanceof Frost) {
|
||||
sprite.add( CharSprite.State.FROZEN );
|
||||
} else if (buff instanceof Light) {
|
||||
sprite.add( CharSprite.State.ILLUMINATED );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int stealth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void move( int step ) {
|
||||
if (Dungeon.level.map[pos] == Terrain.OPEN_DOOR) {
|
||||
Door.leave( pos );
|
||||
}
|
||||
|
||||
pos = step;
|
||||
|
||||
if (flying && Dungeon.level.map[pos] == Terrain.DOOR) {
|
||||
Door.enter( pos );
|
||||
}
|
||||
|
||||
if (this != Dungeon.hero) {
|
||||
sprite.visible = Dungeon.visible[pos];
|
||||
}
|
||||
}
|
||||
|
||||
public int distance( Char other ) {
|
||||
return Level.distance( pos, other.pos );
|
||||
}
|
||||
|
||||
public void onMotionComplete() {
|
||||
next();
|
||||
}
|
||||
|
||||
public void onAttackComplete() {
|
||||
next();
|
||||
}
|
||||
|
||||
public void onOperateComplete() {
|
||||
next();
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> EMPTY = new HashSet<Class<?>>();
|
||||
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class Alchemy extends Blob {
|
||||
|
||||
protected int pos;
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (cur[i] > 0) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void evolve() {
|
||||
volume = off[pos] = cur[pos];
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
Journal.add( Journal.Feature.ALCHEMY );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seed( int cell, int amount ) {
|
||||
cur[pos] = 0;
|
||||
pos = cell;
|
||||
volume = cur[pos] = amount;
|
||||
}
|
||||
|
||||
public static void transmute( int cell ) {
|
||||
Heap heap = Dungeon.level.heaps.get( cell );
|
||||
if (heap != null) {
|
||||
|
||||
Item result = heap.transmute();
|
||||
if (result != null) {
|
||||
Dungeon.level.drop( result, cell ).sprite.drop( cell );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
emitter.start( Speck.factory( Speck.BUBBLE ), 0.4f, 0 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class Blob extends Actor {
|
||||
|
||||
public static final int WIDTH = Level.WIDTH;
|
||||
public static final int HEIGHT = Level.HEIGHT;
|
||||
public static final int LENGTH = Level.LENGTH;
|
||||
|
||||
public int volume = 0;
|
||||
|
||||
public int[] cur;
|
||||
protected int[] off;
|
||||
|
||||
public BlobEmitter emitter;
|
||||
|
||||
protected Blob() {
|
||||
|
||||
cur = new int[LENGTH];
|
||||
off = new int[LENGTH];
|
||||
|
||||
volume = 0;
|
||||
}
|
||||
|
||||
private static final String CUR = "cur";
|
||||
private static final String START = "start";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
|
||||
if (volume > 0) {
|
||||
|
||||
int start;
|
||||
for (start=0; start < LENGTH; start++) {
|
||||
if (cur[start] > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int end;
|
||||
for (end=LENGTH-1; end > start; end--) {
|
||||
if (cur[end] > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bundle.put( START, start );
|
||||
bundle.put( CUR, trim( start, end + 1 ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private int[] trim( int start, int end ) {
|
||||
int len = end - start;
|
||||
int[] copy = new int[len];
|
||||
System.arraycopy( cur, start, copy, 0, len );
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
super.restoreFromBundle( bundle );
|
||||
|
||||
int[] data = bundle.getIntArray( CUR );
|
||||
if (data != null) {
|
||||
int start = bundle.getInt( START );
|
||||
for (int i=0; i < data.length; i++) {
|
||||
cur[i + start] = data[i];
|
||||
volume += data[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (Level.resizingNeeded) {
|
||||
int[] cur = new int[Level.LENGTH];
|
||||
Arrays.fill( cur, 0 );
|
||||
|
||||
int loadedMapSize = Level.loadedMapSize;
|
||||
for (int i=0; i < loadedMapSize; i++) {
|
||||
System.arraycopy( this.cur, i * loadedMapSize, cur, i * Level.WIDTH, loadedMapSize );
|
||||
}
|
||||
|
||||
this.cur = cur;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
|
||||
spend( TICK );
|
||||
|
||||
if (volume > 0) {
|
||||
|
||||
volume = 0;
|
||||
evolve();
|
||||
|
||||
int[] tmp = off;
|
||||
off = cur;
|
||||
cur = tmp;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void use( BlobEmitter emitter ) {
|
||||
this.emitter = emitter;
|
||||
}
|
||||
|
||||
protected void evolve() {
|
||||
|
||||
boolean[] notBlocking = BArray.not( Level.solid, null );
|
||||
|
||||
for (int i=1; i < HEIGHT-1; i++) {
|
||||
|
||||
int from = i * WIDTH + 1;
|
||||
int to = from + WIDTH - 2;
|
||||
|
||||
for (int pos=from; pos < to; pos++) {
|
||||
if (notBlocking[pos]) {
|
||||
|
||||
int count = 1;
|
||||
int sum = cur[pos];
|
||||
|
||||
if (notBlocking[pos-1]) {
|
||||
sum += cur[pos-1];
|
||||
count++;
|
||||
}
|
||||
if (notBlocking[pos+1]) {
|
||||
sum += cur[pos+1];
|
||||
count++;
|
||||
}
|
||||
if (notBlocking[pos-WIDTH]) {
|
||||
sum += cur[pos-WIDTH];
|
||||
count++;
|
||||
}
|
||||
if (notBlocking[pos+WIDTH]) {
|
||||
sum += cur[pos+WIDTH];
|
||||
count++;
|
||||
}
|
||||
|
||||
int value = sum >= count ? (sum / count) - 1 : 0;
|
||||
off[pos] = value;
|
||||
|
||||
volume += value;
|
||||
} else {
|
||||
off[pos] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void seed( int cell, int amount ) {
|
||||
cur[cell] += amount;
|
||||
volume += amount;
|
||||
}
|
||||
|
||||
public void clear( int cell ) {
|
||||
volume -= cur[cell];
|
||||
cur[cell] = 0;
|
||||
}
|
||||
|
||||
public String tileDesc() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static<T extends Blob> T seed( int cell, int amount, Class<T> type ) {
|
||||
try {
|
||||
|
||||
T gas = (T)Dungeon.level.blobs.get( type );
|
||||
if (gas == null) {
|
||||
gas = type.newInstance();
|
||||
Dungeon.level.blobs.put( type, gas );
|
||||
}
|
||||
|
||||
gas.seed( cell, amount );
|
||||
|
||||
return gas;
|
||||
|
||||
} catch (Exception e) {
|
||||
ShatteredPixelDungeon.reportException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
|
||||
public class Fire extends Blob {
|
||||
|
||||
@Override
|
||||
protected void evolve() {
|
||||
|
||||
boolean[] flamable = Level.flamable;
|
||||
|
||||
int from = WIDTH + 1;
|
||||
int to = Level.LENGTH - WIDTH - 1;
|
||||
|
||||
boolean observe = false;
|
||||
|
||||
for (int pos=from; pos < to; pos++) {
|
||||
|
||||
int fire;
|
||||
|
||||
if (cur[pos] > 0) {
|
||||
|
||||
burn( pos );
|
||||
|
||||
fire = cur[pos] - 1;
|
||||
if (fire <= 0 && flamable[pos]) {
|
||||
|
||||
int oldTile = Dungeon.level.map[pos];
|
||||
Level.set( pos, Terrain.EMBERS );
|
||||
|
||||
observe = true;
|
||||
GameScene.updateMap( pos );
|
||||
if (Dungeon.visible[pos]) {
|
||||
GameScene.discoverTile( pos, oldTile );
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (flamable[pos] && (cur[pos-1] > 0 || cur[pos+1] > 0 || cur[pos-WIDTH] > 0 || cur[pos+WIDTH] > 0)) {
|
||||
fire = 4;
|
||||
burn( pos );
|
||||
} else {
|
||||
fire = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
volume += (off[pos] = fire);
|
||||
|
||||
}
|
||||
|
||||
if (observe) {
|
||||
Dungeon.observe();
|
||||
}
|
||||
}
|
||||
|
||||
private void burn( int pos ) {
|
||||
Char ch = Actor.findChar( pos );
|
||||
if (ch != null) {
|
||||
Buff.affect( ch, Burning.class ).reignite( ch );
|
||||
}
|
||||
|
||||
Heap heap = Dungeon.level.heaps.get( pos );
|
||||
if (heap != null) {
|
||||
heap.burn();
|
||||
}
|
||||
}
|
||||
|
||||
public void seed( int cell, int amount ) {
|
||||
if (cur[cell] == 0) {
|
||||
volume += amount;
|
||||
cur[cell] = amount;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
emitter.start( FlameParticle.FACTORY, 0.03f, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc() {
|
||||
return "A fire is raging here.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Shadows;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShaftParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
|
||||
public class Foliage extends Blob {
|
||||
|
||||
@Override
|
||||
protected void evolve() {
|
||||
|
||||
int from = WIDTH + 1;
|
||||
int to = Level.LENGTH - WIDTH - 1;
|
||||
|
||||
int[] map = Dungeon.level.map;
|
||||
boolean regrowth = false;
|
||||
|
||||
boolean visible = false;
|
||||
|
||||
for (int pos=from; pos < to; pos++) {
|
||||
if (cur[pos] > 0) {
|
||||
|
||||
off[pos] = cur[pos];
|
||||
volume += off[pos];
|
||||
|
||||
if (map[pos] == Terrain.EMBERS) {
|
||||
map[pos] = Terrain.GRASS;
|
||||
regrowth = true;
|
||||
}
|
||||
|
||||
visible = visible || Dungeon.visible[pos];
|
||||
|
||||
} else {
|
||||
off[pos] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Hero hero = Dungeon.hero;
|
||||
if (hero.isAlive() && hero.visibleEnemies() == 0 && cur[hero.pos] > 0) {
|
||||
Buff.affect( hero, Shadows.class ).prolong();
|
||||
}
|
||||
|
||||
if (regrowth) {
|
||||
GameScene.updateMap();
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
Journal.add( Journal.Feature.GARDEN );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
emitter.start( ShaftParticle.FACTORY, 0.9f, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc() {
|
||||
return "Shafts of light pierce the gloom of the underground garden.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SnowParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Freezing {
|
||||
|
||||
// It's not really a blob...
|
||||
|
||||
public static void affect( int cell, Fire fire ) {
|
||||
|
||||
Char ch = Actor.findChar( cell );
|
||||
if (ch != null) {
|
||||
Buff.prolong( ch, Frost.class, Frost.duration( ch ) * Random.Float( 1.0f, 1.5f ) );
|
||||
}
|
||||
|
||||
if (fire != null) {
|
||||
fire.clear( cell );
|
||||
}
|
||||
|
||||
Heap heap = Dungeon.level.heaps.get( cell );
|
||||
if (heap != null) {
|
||||
heap.freeze();
|
||||
}
|
||||
|
||||
if (Dungeon.visible[cell]) {
|
||||
CellEmitter.get( cell ).start( SnowParticle.FACTORY, 0.2f, 6 );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
|
||||
public class ParalyticGas extends Blob {
|
||||
|
||||
@Override
|
||||
protected void evolve() {
|
||||
super.evolve();
|
||||
|
||||
Char ch;
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (cur[i] > 0 && (ch = Actor.findChar( i )) != null) {
|
||||
Buff.prolong( ch, Paralysis.class, Paralysis.duration( ch ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
|
||||
emitter.pour( Speck.factory( Speck.PARALYSIS ), 0.6f );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc() {
|
||||
return "A cloud of paralytic gas is swirling here.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
|
||||
public class Regrowth extends Blob {
|
||||
|
||||
@Override
|
||||
protected void evolve() {
|
||||
super.evolve();
|
||||
|
||||
if (volume > 0) {
|
||||
|
||||
boolean mapUpdated = false;
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (off[i] > 0) {
|
||||
int c = Dungeon.level.map[i];
|
||||
if (c == Terrain.EMPTY || c == Terrain.EMBERS || c == Terrain.EMPTY_DECO) {
|
||||
|
||||
Level.set( i, cur[i] > 9 ? Terrain.HIGH_GRASS : Terrain.GRASS );
|
||||
mapUpdated = true;
|
||||
|
||||
} else if (c == Terrain.GRASS && cur[i] > 9) {
|
||||
|
||||
Level.set( i, Terrain.HIGH_GRASS );
|
||||
mapUpdated = true;
|
||||
|
||||
}
|
||||
|
||||
Char ch = Actor.findChar( i );
|
||||
if (ch != null) {
|
||||
Buff.prolong( ch, Roots.class, TICK );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mapUpdated) {
|
||||
GameScene.updateMap();
|
||||
Dungeon.observe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
|
||||
emitter.start( LeafParticle.LEVEL_SPECIFIC, 0.2f, 0 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
|
||||
public class ToxicGas extends Blob implements Hero.Doom {
|
||||
|
||||
@Override
|
||||
protected void evolve() {
|
||||
super.evolve();
|
||||
|
||||
int levelDamage = 5 + Dungeon.depth * 5;
|
||||
|
||||
Char ch;
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (cur[i] > 0 && (ch = Actor.findChar( i )) != null) {
|
||||
|
||||
int damage = (ch.HT + levelDamage) / 40;
|
||||
if (damage < 1) {
|
||||
damage = 1;
|
||||
}
|
||||
|
||||
ch.damage( damage, this );
|
||||
}
|
||||
}
|
||||
|
||||
Blob blob = Dungeon.level.blobs.get( ParalyticGas.class );
|
||||
if (blob != null) {
|
||||
|
||||
int par[] = blob.cur;
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
|
||||
int t = cur[i];
|
||||
int p = par[i];
|
||||
|
||||
if (p >= t) {
|
||||
volume -= t;
|
||||
cur[i] = 0;
|
||||
} else {
|
||||
blob.volume -= p;
|
||||
par[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
|
||||
emitter.pour( Speck.factory( Speck.TOXIC ), 0.6f );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc() {
|
||||
return "A greenish cloud of toxic gas is swirling here.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath() {
|
||||
|
||||
Badges.validateDeathFromGas();
|
||||
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.GAS, Dungeon.depth ) );
|
||||
GLog.n( "You died from a toxic gas.." );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
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.DungeonTilemap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal.Feature;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Awareness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Identification;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
|
||||
public class WaterOfAwareness extends WellWater {
|
||||
|
||||
private static final String TXT_PROCCED =
|
||||
"As you take a sip, you feel the knowledge pours into your mind. " +
|
||||
"Now you know everything about your equipped items. Also you sense " +
|
||||
"all items on the level and know all its secrets.";
|
||||
|
||||
@Override
|
||||
protected boolean affectHero( Hero hero ) {
|
||||
|
||||
Sample.INSTANCE.play( Assets.SND_DRINK );
|
||||
emitter.parent.add( new Identification( DungeonTilemap.tileCenterToWorld( pos ) ) );
|
||||
|
||||
hero.belongings.observe();
|
||||
|
||||
for (int i=0; i < Level.LENGTH; i++) {
|
||||
|
||||
int terr = Dungeon.level.map[i];
|
||||
if ((Terrain.flags[terr] & Terrain.SECRET) != 0) {
|
||||
|
||||
Level.set( i, Terrain.discover( terr ) );
|
||||
GameScene.updateMap( i );
|
||||
|
||||
if (Dungeon.visible[i]) {
|
||||
GameScene.discoverTile( i, terr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Buff.affect( hero, Awareness.class, Awareness.DURATION );
|
||||
Dungeon.observe();
|
||||
|
||||
Dungeon.hero.interrupt();
|
||||
|
||||
GLog.p( TXT_PROCCED );
|
||||
|
||||
Journal.remove( Feature.WELL_OF_AWARENESS );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item affectItem( Item item ) {
|
||||
if (item.isIdentified()) {
|
||||
return null;
|
||||
} else {
|
||||
item.identify();
|
||||
Badges.validateItemLevelAquired( item );
|
||||
|
||||
emitter.parent.add( new Identification( DungeonTilemap.tileCenterToWorld( pos ) ) );
|
||||
|
||||
Journal.remove( Feature.WELL_OF_AWARENESS );
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
emitter.pour( Speck.factory( Speck.QUESTION ), 0.3f );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc() {
|
||||
return
|
||||
"Power of knowledge radiates from the water of this well. " +
|
||||
"Take a sip from it to reveal all secrets of equipped items.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
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.Journal.Feature;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShaftParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.DewVial;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
|
||||
public class WaterOfHealth extends WellWater {
|
||||
|
||||
private static final String TXT_PROCCED =
|
||||
"As you take a sip, you feel your wounds heal completely.";
|
||||
|
||||
@Override
|
||||
protected boolean affectHero( Hero hero ) {
|
||||
|
||||
Sample.INSTANCE.play( Assets.SND_DRINK );
|
||||
|
||||
PotionOfHealing.heal( hero );
|
||||
hero.belongings.uncurseEquipped();
|
||||
((Hunger)hero.buff( Hunger.class )).satisfy( Hunger.STARVING );
|
||||
|
||||
CellEmitter.get( pos ).start( ShaftParticle.FACTORY, 0.2f, 3 );
|
||||
|
||||
Dungeon.hero.interrupt();
|
||||
|
||||
GLog.p( TXT_PROCCED );
|
||||
|
||||
Journal.remove( Feature.WELL_OF_HEALTH );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item affectItem( Item item ) {
|
||||
if (item instanceof DewVial && !((DewVial)item).isFull()) {
|
||||
((DewVial)item).fill();
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
emitter.start( Speck.factory( Speck.HEALING ), 0.5f, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc() {
|
||||
return
|
||||
"Power of health radiates from the water of this well. " +
|
||||
"Take a sip from it to heal your wounds and satisfy hunger.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal.Feature;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator.Category;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfMight;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfWeaponUpgrade;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon.Enchantment;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.*;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.plants.Plant;
|
||||
|
||||
public class WaterOfTransmutation extends WellWater {
|
||||
|
||||
@Override
|
||||
protected Item affectItem( Item item ) {
|
||||
|
||||
if (item instanceof MeleeWeapon) {
|
||||
|
||||
return changeWeapon( (MeleeWeapon)item );
|
||||
|
||||
} else if (item instanceof Scroll) {
|
||||
|
||||
Journal.remove( Feature.WELL_OF_TRANSMUTATION );
|
||||
return changeScroll( (Scroll)item );
|
||||
|
||||
} else if (item instanceof Potion) {
|
||||
|
||||
Journal.remove( Feature.WELL_OF_TRANSMUTATION );
|
||||
return changePotion( (Potion)item );
|
||||
|
||||
} else if (item instanceof Ring) {
|
||||
|
||||
Journal.remove( Feature.WELL_OF_TRANSMUTATION );
|
||||
return changeRing( (Ring)item );
|
||||
|
||||
} else if (item instanceof Wand) {
|
||||
|
||||
Journal.remove( Feature.WELL_OF_TRANSMUTATION );
|
||||
return changeWand( (Wand)item );
|
||||
|
||||
} else if (item instanceof Plant.Seed) {
|
||||
|
||||
Journal.remove( Feature.WELL_OF_TRANSMUTATION );
|
||||
return changeSeed( (Plant.Seed)item );
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
emitter.start( Speck.factory( Speck.CHANGE ), 0.2f, 0 );
|
||||
}
|
||||
|
||||
private MeleeWeapon changeWeapon( MeleeWeapon w ) {
|
||||
|
||||
MeleeWeapon n = null;
|
||||
|
||||
if (w instanceof Knuckles) {
|
||||
n = new Dagger();
|
||||
} else if (w instanceof Dagger) {
|
||||
n = new Knuckles();
|
||||
}
|
||||
|
||||
else if (w instanceof Spear) {
|
||||
n = new Quarterstaff();
|
||||
} else if (w instanceof Quarterstaff) {
|
||||
n = new Spear();
|
||||
}
|
||||
|
||||
else if (w instanceof Sword) {
|
||||
n = new Mace();
|
||||
} else if (w instanceof Mace) {
|
||||
n = new Sword();
|
||||
}
|
||||
|
||||
else if (w instanceof Longsword) {
|
||||
n = new BattleAxe();
|
||||
} else if (w instanceof BattleAxe) {
|
||||
n = new Longsword();
|
||||
}
|
||||
|
||||
else if (w instanceof Glaive) {
|
||||
n = new WarHammer();
|
||||
} else if (w instanceof WarHammer) {
|
||||
n = new Glaive();
|
||||
}
|
||||
|
||||
if (n != null) {
|
||||
|
||||
int level = w.level;
|
||||
if (level > 0) {
|
||||
n.upgrade( level );
|
||||
} else if (level < 0) {
|
||||
n.degrade( -level );
|
||||
}
|
||||
|
||||
if (w.isEnchanted()) {
|
||||
n.enchant( Enchantment.random() );
|
||||
}
|
||||
|
||||
n.levelKnown = w.levelKnown;
|
||||
n.cursedKnown = w.cursedKnown;
|
||||
n.cursed = w.cursed;
|
||||
|
||||
Journal.remove( Feature.WELL_OF_TRANSMUTATION );
|
||||
|
||||
return n;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Ring changeRing( Ring r ) {
|
||||
Ring n;
|
||||
do {
|
||||
n = (Ring)Generator.random( Category.RING );
|
||||
} while (n.getClass() == r.getClass());
|
||||
|
||||
n.level = 0;
|
||||
|
||||
int level = r.level;
|
||||
if (level > 0) {
|
||||
n.upgrade( level );
|
||||
} else if (level < 0) {
|
||||
n.degrade( -level );
|
||||
}
|
||||
|
||||
n.levelKnown = r.levelKnown;
|
||||
n.cursedKnown = r.cursedKnown;
|
||||
n.cursed = r.cursed;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
private Wand changeWand( Wand w ) {
|
||||
|
||||
Wand n;
|
||||
do {
|
||||
n = (Wand)Generator.random( Category.WAND );
|
||||
} while (n.getClass() == w.getClass());
|
||||
|
||||
n.level = 0;
|
||||
n.upgrade( w.level );
|
||||
|
||||
n.levelKnown = w.levelKnown;
|
||||
n.cursedKnown = w.cursedKnown;
|
||||
n.cursed = w.cursed;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
private Plant.Seed changeSeed( Plant.Seed s ) {
|
||||
|
||||
Plant.Seed n;
|
||||
|
||||
do {
|
||||
n = (Plant.Seed)Generator.random( Category.SEED );
|
||||
} while (n.getClass() == s.getClass());
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
private Scroll changeScroll( Scroll s ) {
|
||||
if (s instanceof ScrollOfUpgrade) {
|
||||
|
||||
return new ScrollOfWeaponUpgrade();
|
||||
|
||||
} else if (s instanceof ScrollOfWeaponUpgrade) {
|
||||
|
||||
return new ScrollOfUpgrade();
|
||||
|
||||
} else {
|
||||
|
||||
Scroll n;
|
||||
do {
|
||||
n = (Scroll)Generator.random( Category.SCROLL );
|
||||
} while (n.getClass() == s.getClass());
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
private Potion changePotion( Potion p ) {
|
||||
if (p instanceof PotionOfStrength) {
|
||||
|
||||
return new PotionOfMight();
|
||||
|
||||
} else if (p instanceof PotionOfMight) {
|
||||
|
||||
return new PotionOfStrength();
|
||||
|
||||
} else {
|
||||
|
||||
Potion n;
|
||||
do {
|
||||
n = (Potion)Generator.random( Category.POTION );
|
||||
} while (n.getClass() == p.getClass());
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc() {
|
||||
return
|
||||
"Power of change radiates from the water of this well. " +
|
||||
"Throw an item into the well to turn it into something else.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.WebParticle;
|
||||
|
||||
public class Web extends Blob {
|
||||
|
||||
@Override
|
||||
protected void evolve() {
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
|
||||
int offv = cur[i] > 0 ? cur[i] - 1 : 0;
|
||||
off[i] = offv;
|
||||
|
||||
if (offv > 0) {
|
||||
|
||||
volume += offv;
|
||||
|
||||
Char ch = Actor.findChar( i );
|
||||
if (ch != null) {
|
||||
Buff.prolong( ch, Roots.class, TICK );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use( BlobEmitter emitter ) {
|
||||
super.use( emitter );
|
||||
|
||||
emitter.pour( WebParticle.FACTORY, 0.4f );
|
||||
}
|
||||
|
||||
public void seed( int cell, int amount ) {
|
||||
int diff = amount - cur[cell];
|
||||
if (diff > 0) {
|
||||
cur[cell] = amount;
|
||||
volume += diff;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc() {
|
||||
return "Everything is covered with a thick web here.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.blobs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal.Feature;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class WellWater extends Blob {
|
||||
|
||||
protected int pos;
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (cur[i] > 0) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void evolve() {
|
||||
volume = off[pos] = cur[pos];
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
if (this instanceof WaterOfAwareness) {
|
||||
Journal.add( Feature.WELL_OF_AWARENESS );
|
||||
} else if (this instanceof WaterOfHealth) {
|
||||
Journal.add( Feature.WELL_OF_HEALTH );
|
||||
} else if (this instanceof WaterOfTransmutation) {
|
||||
Journal.add( Feature.WELL_OF_TRANSMUTATION );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean affect() {
|
||||
|
||||
Heap heap;
|
||||
|
||||
if (pos == Dungeon.hero.pos && affectHero( Dungeon.hero )) {
|
||||
|
||||
volume = off[pos] = cur[pos] = 0;
|
||||
return true;
|
||||
|
||||
} else if ((heap = Dungeon.level.heaps.get( pos )) != null) {
|
||||
|
||||
Item oldItem = heap.peek();
|
||||
Item newItem = affectItem( oldItem );
|
||||
|
||||
if (newItem != null) {
|
||||
|
||||
if (newItem == oldItem) {
|
||||
|
||||
} else if (oldItem.quantity() > 1) {
|
||||
|
||||
oldItem.quantity( oldItem.quantity() - 1 );
|
||||
heap.drop( newItem );
|
||||
|
||||
} else {
|
||||
heap.replace( oldItem, newItem );
|
||||
}
|
||||
|
||||
heap.sprite.link();
|
||||
volume = off[pos] = cur[pos] = 0;
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
int newPlace;
|
||||
do {
|
||||
newPlace = pos + Level.NEIGHBOURS8[Random.Int( 8 )];
|
||||
} while (!Level.passable[newPlace] && !Level.avoid[newPlace]);
|
||||
Dungeon.level.drop( heap.pickUp(), newPlace ).sprite.drop( pos );
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean affectHero( Hero hero ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Item affectItem( Item item ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seed( int cell, int amount ) {
|
||||
cur[pos] = 0;
|
||||
pos = cell;
|
||||
volume = cur[pos] = amount;
|
||||
}
|
||||
|
||||
public static void affectCell( int cell ) {
|
||||
|
||||
Class<?>[] waters = {WaterOfHealth.class, WaterOfAwareness.class, WaterOfTransmutation.class};
|
||||
|
||||
for (Class<?>waterClass : waters) {
|
||||
WellWater water = (WellWater)Dungeon.level.blobs.get( waterClass );
|
||||
if (water != null &&
|
||||
water.volume > 0 &&
|
||||
water.pos == cell &&
|
||||
water.affect()) {
|
||||
|
||||
Level.set( cell, Terrain.EMPTY_WELL );
|
||||
GameScene.updateMap( cell );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Amok extends FlavourBuff {
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.AMOK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Amok";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
|
||||
public class Awareness extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 2f;
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
super.detach();
|
||||
Dungeon.observe();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Barkskin extends Buff {
|
||||
|
||||
private int level = 0;
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (target.isAlive()) {
|
||||
|
||||
spend( TICK );
|
||||
if (--level <= 0) {
|
||||
detach();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
detach();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int level() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public void level( int value ) {
|
||||
if (level < value) {
|
||||
level = value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.BARKSKIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Barkskin";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Bleeding extends Buff {
|
||||
|
||||
protected int level;
|
||||
|
||||
private static final String LEVEL = "level";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( LEVEL, level );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
level = bundle.getInt( LEVEL );
|
||||
}
|
||||
|
||||
public void set( int level ) {
|
||||
this.level = level;
|
||||
};
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.BLEEDING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Bleeding";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (target.isAlive()) {
|
||||
|
||||
if ((level = Random.Int( level / 2, level )) > 0) {
|
||||
|
||||
target.damage( level, this );
|
||||
if (target.sprite.visible) {
|
||||
Splash.at( target.sprite.center(), -PointF.PI / 2, PointF.PI / 6,
|
||||
target.sprite.blood(), Math.min( 10 * level / target.HT, 10 ) );
|
||||
}
|
||||
|
||||
if (target == Dungeon.hero && !target.isAlive()) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.BLEEDING, Dungeon.depth ) );
|
||||
GLog.n( "You bled to death..." );
|
||||
}
|
||||
|
||||
spend( TICK );
|
||||
} else {
|
||||
detach();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
detach();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Blindness extends FlavourBuff {
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
super.detach();
|
||||
Dungeon.observe();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.BLINDNESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Blinded";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Buff extends Actor {
|
||||
|
||||
public Char target;
|
||||
|
||||
public boolean attachTo( Char target ) {
|
||||
|
||||
if (target.immunities().contains( getClass() )) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.target = target;
|
||||
target.add( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void detach() {
|
||||
target.remove( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
diactivate();
|
||||
return true;
|
||||
}
|
||||
|
||||
public int icon() {
|
||||
return BuffIndicator.NONE;
|
||||
}
|
||||
|
||||
public static<T extends Buff> T affect( Char target, Class<T> buffClass ) {
|
||||
T buff = target.buff( buffClass );
|
||||
if (buff != null) {
|
||||
return buff;
|
||||
} else {
|
||||
try {
|
||||
buff = buffClass.newInstance();
|
||||
buff.attachTo( target );
|
||||
return buff;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static<T extends FlavourBuff> T affect( Char target, Class<T> buffClass, float duration ) {
|
||||
T buff = affect( target, buffClass );
|
||||
buff.spend( duration );
|
||||
return buff;
|
||||
}
|
||||
|
||||
public static<T extends FlavourBuff> T prolong( Char target, Class<T> buffClass, float duration ) {
|
||||
T buff = affect( target, buffClass );
|
||||
buff.postpone( duration );
|
||||
return buff;
|
||||
}
|
||||
|
||||
public static void detach( Buff buff ) {
|
||||
if (buff != null) {
|
||||
buff.detach();
|
||||
}
|
||||
}
|
||||
|
||||
public static void detach( Char target, Class<? extends Buff> cl ) {
|
||||
detach( target.buff( cl ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Thief;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.ChargrilledMeat;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.Resistance;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Burning extends Buff implements Hero.Doom {
|
||||
|
||||
private static final String TXT_BURNS_UP = "%s burns up!";
|
||||
private static final String TXT_BURNED_TO_DEATH = "You burned to death...";
|
||||
|
||||
private static final float DURATION = 8f;
|
||||
|
||||
private float left;
|
||||
|
||||
private static final String LEFT = "left";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( LEFT, left );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle(bundle);
|
||||
left = bundle.getFloat( LEFT );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
|
||||
if (target.isAlive()) {
|
||||
|
||||
if (target instanceof Hero) {
|
||||
Buff.prolong( target, Light.class, TICK * 1.01f );
|
||||
}
|
||||
|
||||
target.damage( Random.Int( 1, 5 ), this );
|
||||
|
||||
if (target instanceof Hero) {
|
||||
|
||||
Item item = ((Hero)target).belongings.randomUnequipped();
|
||||
if (item instanceof Scroll) {
|
||||
|
||||
item = item.detach( ((Hero)target).belongings.backpack );
|
||||
GLog.w( TXT_BURNS_UP, item.toString() );
|
||||
|
||||
Heap.burnFX( target.pos );
|
||||
|
||||
} else if (item instanceof MysteryMeat) {
|
||||
|
||||
item = item.detach( ((Hero)target).belongings.backpack );
|
||||
ChargrilledMeat steak = new ChargrilledMeat();
|
||||
if (!steak.collect( ((Hero)target).belongings.backpack )) {
|
||||
Dungeon.level.drop( steak, target.pos ).sprite.drop();
|
||||
}
|
||||
GLog.w( TXT_BURNS_UP, item.toString() );
|
||||
|
||||
Heap.burnFX( target.pos );
|
||||
|
||||
}
|
||||
|
||||
} else if (target instanceof Thief && ((Thief)target).item instanceof Scroll) {
|
||||
|
||||
((Thief)target).item = null;
|
||||
target.sprite.emitter().burst( ElmoParticle.FACTORY, 6 );
|
||||
}
|
||||
|
||||
} else {
|
||||
detach();
|
||||
}
|
||||
|
||||
if (Level.flamable[target.pos]) {
|
||||
GameScene.add( Blob.seed( target.pos, 4, Fire.class ) );
|
||||
}
|
||||
|
||||
spend( TICK );
|
||||
left -= TICK;
|
||||
|
||||
if (left <= 0 ||
|
||||
Random.Float() > (2 + (float)target.HP / target.HT) / 3 ||
|
||||
(Level.water[target.pos] && !target.flying)) {
|
||||
|
||||
detach();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void reignite( Char ch ) {
|
||||
left = duration( ch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.FIRE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Burning";
|
||||
}
|
||||
|
||||
public static float duration( Char ch ) {
|
||||
Resistance r = ch.buff( Resistance.class );
|
||||
return r != null ? r.durationFactor() * DURATION : DURATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath() {
|
||||
|
||||
Badges.validateDeathFromFire();
|
||||
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.BURNING, Dungeon.depth ) );
|
||||
GLog.n( TXT_BURNED_TO_DEATH );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.Resistance;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Charm extends FlavourBuff {
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (super.attachTo( target )) {
|
||||
target.pacified = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
target.pacified = false;
|
||||
super.detach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.HEART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Charmed";
|
||||
}
|
||||
|
||||
public static float durationFactor( Char ch ) {
|
||||
Resistance r = ch.buff( Resistance.class );
|
||||
return r != null ? r.durationFactor() : 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
|
||||
public class Combo extends Buff {
|
||||
|
||||
private static String TXT_COMBO = "%d hit combo!";
|
||||
|
||||
public int count = 0;
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.COMBO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Combo";
|
||||
}
|
||||
|
||||
public int hit( Char enemy, int damage ) {
|
||||
|
||||
count++;
|
||||
|
||||
if (count >= 3) {
|
||||
|
||||
Badges.validateMasteryCombo( count );
|
||||
|
||||
GLog.p( TXT_COMBO, count );
|
||||
postpone( 1.41f - count / 10f );
|
||||
return (int)(damage * (count - 2) / 5f);
|
||||
|
||||
} else {
|
||||
|
||||
postpone( 1.1f );
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
detach();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Cripple extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 10f;
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.CRIPPLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Crippled";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
// Special kind of buff, that doesn't perform any kind actions
|
||||
public class FlavourBuff extends Buff {
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
detach();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.FrozenCarpaccio;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.Resistance;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Frost extends FlavourBuff {
|
||||
|
||||
private static final float DURATION = 5f;
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (super.attachTo( target )) {
|
||||
|
||||
target.paralysed = true;
|
||||
Burning.detach( target, Burning.class );
|
||||
|
||||
if (target instanceof Hero) {
|
||||
Hero hero = (Hero)target;
|
||||
Item item = hero.belongings.randomUnequipped();
|
||||
if (item instanceof MysteryMeat) {
|
||||
|
||||
item = item.detach( hero.belongings.backpack );
|
||||
FrozenCarpaccio carpaccio = new FrozenCarpaccio();
|
||||
if (!carpaccio.collect( hero.belongings.backpack )) {
|
||||
Dungeon.level.drop( carpaccio, target.pos ).sprite.drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
target.paralysed = false;
|
||||
super.detach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.FROST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Frozen";
|
||||
}
|
||||
|
||||
public static float duration( Char ch ) {
|
||||
Resistance r = ch.buff( Resistance.class );
|
||||
return r != null ? r.durationFactor() * DURATION : DURATION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Fury extends Buff {
|
||||
|
||||
public static float LEVEL = 0.4f;
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (target.HP > target.HT * LEVEL) {
|
||||
detach();
|
||||
}
|
||||
|
||||
spend( TICK );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.FURY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Fury";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class GasesImmunity extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 5f;
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.IMMUNITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Immune to gases";
|
||||
}
|
||||
|
||||
public static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Paralysis.class );
|
||||
IMMUNITIES.add( ToxicGas.class );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfSatiety;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Hunger extends Buff implements Hero.Doom {
|
||||
|
||||
private static final float STEP = 10f;
|
||||
|
||||
public static final float HUNGRY = 260f;
|
||||
public static final float STARVING = 360f;
|
||||
|
||||
private static final String TXT_HUNGRY = "You are hungry.";
|
||||
private static final String TXT_STARVING = "You are starving!";
|
||||
private static final String TXT_DEATH = "You starved to death...";
|
||||
|
||||
private float level;
|
||||
|
||||
private static final String LEVEL = "level";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( LEVEL, level );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
level = bundle.getFloat( LEVEL );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (target.isAlive()) {
|
||||
|
||||
Hero hero = (Hero)target;
|
||||
|
||||
if (isStarving()) {
|
||||
|
||||
if (Random.Float() < 0.3f && (target.HP > 1 || !target.paralysed)) {
|
||||
|
||||
GLog.n( TXT_STARVING );
|
||||
hero.damage( 1, this );
|
||||
|
||||
hero.interrupt();
|
||||
}
|
||||
} else {
|
||||
|
||||
int bonus = 0;
|
||||
for (Buff buff : target.buffs( RingOfSatiety.Satiety.class )) {
|
||||
bonus += ((RingOfSatiety.Satiety)buff).level;
|
||||
}
|
||||
|
||||
float newLevel = level + STEP - bonus;
|
||||
boolean statusUpdated = false;
|
||||
if (newLevel >= STARVING) {
|
||||
|
||||
GLog.n( TXT_STARVING );
|
||||
statusUpdated = true;
|
||||
|
||||
hero.interrupt();
|
||||
|
||||
} else if (newLevel >= HUNGRY && level < HUNGRY) {
|
||||
|
||||
GLog.w( TXT_HUNGRY );
|
||||
statusUpdated = true;
|
||||
|
||||
}
|
||||
level = newLevel;
|
||||
|
||||
if (statusUpdated) {
|
||||
BuffIndicator.refreshHero();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float step = ((Hero)target).heroClass == HeroClass.ROGUE ? STEP * 1.2f : STEP;
|
||||
spend( target.buff( Shadows.class ) == null ? step : step * 1.5f );
|
||||
|
||||
} else {
|
||||
|
||||
diactivate();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void satisfy( float energy ) {
|
||||
level -= energy;
|
||||
if (level < 0) {
|
||||
level = 0;
|
||||
} else if (level > STARVING) {
|
||||
level = STARVING;
|
||||
}
|
||||
|
||||
BuffIndicator.refreshHero();
|
||||
}
|
||||
|
||||
public boolean isStarving() {
|
||||
return level >= STARVING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
if (level < HUNGRY) {
|
||||
return BuffIndicator.NONE;
|
||||
} else if (level < STARVING) {
|
||||
return BuffIndicator.HUNGER;
|
||||
} else {
|
||||
return BuffIndicator.STARVATION;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (level < STARVING) {
|
||||
return "Hungry";
|
||||
} else {
|
||||
return "Starving";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath() {
|
||||
|
||||
Badges.validateDeathFromHunger();
|
||||
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.HUNGER, Dungeon.depth ) );
|
||||
GLog.n( TXT_DEATH );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Invisibility extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 15f;
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (super.attachTo( target )) {
|
||||
target.invisible++;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
target.invisible--;
|
||||
super.detach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.INVISIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Invisible";
|
||||
}
|
||||
|
||||
public static void dispel() {
|
||||
Invisibility buff = Dungeon.hero.buff( Invisibility.class );
|
||||
if (buff != null && Dungeon.hero.visibleEnemies() > 0) {
|
||||
buff.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Levitation extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 20f;
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (super.attachTo( target )) {
|
||||
target.flying = true;
|
||||
Roots.detach( target, Roots.class );
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
target.flying = false;
|
||||
Dungeon.level.press( target.pos, target );
|
||||
super.detach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.LEVITATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Levitating";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Light extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 250f;
|
||||
public static final int DISTANCE = 4;
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (super.attachTo( target )) {
|
||||
// When a level is loading, do nothing
|
||||
if (Dungeon.level != null) {
|
||||
target.viewDistance = Math.max( Dungeon.level.viewDistance, DISTANCE );
|
||||
Dungeon.observe();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
target.viewDistance = Dungeon.level.viewDistance;
|
||||
Dungeon.observe();
|
||||
super.detach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.LIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Illuminated";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class MindVision extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 20f;
|
||||
|
||||
public int distance = 2;
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.MIND_VISION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Mind vision";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
super.detach();
|
||||
Dungeon.observe();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
|
||||
public class Ooze extends Buff {
|
||||
|
||||
private static final String TXT_HERO_KILLED = "%s killed you...";
|
||||
|
||||
public int damage = 1;
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.OOZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Caustic ooze";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (target.isAlive()) {
|
||||
target.damage( damage, this );
|
||||
if (!target.isAlive() && target == Dungeon.hero) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.OOZE, Dungeon.depth ) );
|
||||
GLog.n( TXT_HERO_KILLED, toString() );
|
||||
}
|
||||
spend( TICK );
|
||||
}
|
||||
if (Level.water[target.pos]) {
|
||||
detach();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.Resistance;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Paralysis extends FlavourBuff {
|
||||
|
||||
private static final float DURATION = 10f;
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (super.attachTo( target )) {
|
||||
target.paralysed = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
target.paralysed = false;
|
||||
super.detach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.PARALYSIS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Paralysed";
|
||||
}
|
||||
|
||||
public static float duration( Char ch ) {
|
||||
Resistance r = ch.buff( Resistance.class );
|
||||
return r != null ? r.durationFactor() * DURATION : DURATION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.Resistance;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class Poison extends Buff implements Hero.Doom {
|
||||
|
||||
public static final int DOT = 2;
|
||||
|
||||
protected float left;
|
||||
|
||||
private static final String LEFT = "left";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( LEFT, left );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
left = bundle.getFloat( LEFT );
|
||||
}
|
||||
|
||||
public void set( float duration ) {
|
||||
this.left = duration;
|
||||
};
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.POISON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Poisoned";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (target.isAlive()) {
|
||||
|
||||
target.damage( DOT, this );
|
||||
spend( TICK );
|
||||
|
||||
if ((left -= TICK) <= 0) {
|
||||
detach();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
detach();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static float durationFactor( Char ch ) {
|
||||
Resistance r = ch.buff( Resistance.class );
|
||||
return r != null ? r.durationFactor() : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath() {
|
||||
Badges.validateDeathFromPoison();
|
||||
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.POISON, Dungeon.depth ) );
|
||||
GLog.n( "You died from poison..." );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfMending;
|
||||
|
||||
public class Regeneration extends Buff {
|
||||
|
||||
private static final float REGENERATION_DELAY = 10;
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (target.isAlive()) {
|
||||
|
||||
if (target.HP < target.HT && !((Hero)target).isStarving()) {
|
||||
target.HP += 1;
|
||||
}
|
||||
|
||||
int bonus = 0;
|
||||
for (Buff buff : target.buffs( RingOfMending.Rejuvenation.class )) {
|
||||
bonus += ((RingOfMending.Rejuvenation)buff).level;
|
||||
}
|
||||
|
||||
spend( (float)(REGENERATION_DELAY / Math.pow( 1.2, bonus )) );
|
||||
|
||||
} else {
|
||||
|
||||
diactivate();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Roots extends FlavourBuff {
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (!target.flying && super.attachTo( target )) {
|
||||
target.rooted = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
target.rooted = false;
|
||||
super.detach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.ROOTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Rooted";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class Shadows extends Invisibility {
|
||||
|
||||
protected float left;
|
||||
|
||||
private static final String LEFT = "left";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( LEFT, left );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
left = bundle.getFloat( LEFT );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (super.attachTo( target )) {
|
||||
Sample.INSTANCE.play( Assets.SND_MELD );
|
||||
Dungeon.observe();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
super.detach();
|
||||
Dungeon.observe();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
if (target.isAlive()) {
|
||||
|
||||
spend( TICK * 2 );
|
||||
|
||||
if (--left <= 0 || Dungeon.hero.visibleEnemies() > 0) {
|
||||
detach();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
detach();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void prolong() {
|
||||
left = 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.SHADOWS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Shadowmelded";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
public class Sleep extends FlavourBuff {
|
||||
|
||||
public static final float SWS = 1.5f;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.Resistance;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Slow extends FlavourBuff {
|
||||
|
||||
private static final float DURATION = 10f;
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.SLOW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Slowed";
|
||||
}
|
||||
|
||||
public static float duration( Char ch ) {
|
||||
Resistance r = ch.buff( Resistance.class );
|
||||
return r != null ? r.durationFactor() * DURATION : DURATION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class SnipersMark extends FlavourBuff {
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.MARK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Sniper's mark";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
public class Speed extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 10f;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public class Terror extends FlavourBuff {
|
||||
|
||||
public static final float DURATION = 10f;
|
||||
public Char source;
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.TERROR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
// It's not really correct...
|
||||
source = Dungeon.hero;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Terror";
|
||||
}
|
||||
|
||||
public static void recover( Char target ) {
|
||||
Terror terror = target.buff( Terror.class );
|
||||
if (terror != null && terror.cooldown() < DURATION) {
|
||||
target.remove( terror );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.buffs;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfElements.Resistance;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
|
||||
public class Weakness extends FlavourBuff {
|
||||
|
||||
private static final float DURATION = 40f;
|
||||
|
||||
@Override
|
||||
public int icon() {
|
||||
return BuffIndicator.WEAKNESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Weakened";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean attachTo( Char target ) {
|
||||
if (super.attachTo( target )) {
|
||||
Hero hero = (Hero)target;
|
||||
hero.weakened = true;
|
||||
hero.belongings.discharge();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
super.detach();
|
||||
((Hero)target).weakened = false;
|
||||
}
|
||||
|
||||
public static float duration( Char ch ) {
|
||||
Resistance r = ch.buff( Resistance.class );
|
||||
return r != null ? r.durationFactor() * DURATION : DURATION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* 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.hero;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRemoveCurse;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Belongings implements Iterable<Item> {
|
||||
|
||||
public static final int BACKPACK_SIZE = 19;
|
||||
|
||||
private Hero owner;
|
||||
|
||||
public Bag backpack;
|
||||
|
||||
public KindOfWeapon weapon = null;
|
||||
public Armor armor = null;
|
||||
public Ring ring1 = null;
|
||||
public Ring ring2 = null;
|
||||
|
||||
public Belongings( Hero owner ) {
|
||||
this.owner = owner;
|
||||
|
||||
backpack = new Bag() {{
|
||||
name = "backpack";
|
||||
size = BACKPACK_SIZE;
|
||||
}};
|
||||
backpack.owner = owner;
|
||||
}
|
||||
|
||||
private static final String WEAPON = "weapon";
|
||||
private static final String ARMOR = "armor";
|
||||
private static final String RING1 = "ring1";
|
||||
private static final String RING2 = "ring2";
|
||||
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
|
||||
backpack.storeInBundle( bundle );
|
||||
|
||||
bundle.put( WEAPON, weapon );
|
||||
bundle.put( ARMOR, armor );
|
||||
bundle.put( RING1, ring1 );
|
||||
bundle.put( RING2, ring2 );
|
||||
}
|
||||
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
backpack.clear();
|
||||
backpack.restoreFromBundle( bundle );
|
||||
|
||||
weapon = (KindOfWeapon)bundle.get( WEAPON );
|
||||
if (weapon != null) {
|
||||
weapon.activate( owner );
|
||||
}
|
||||
|
||||
armor = (Armor)bundle.get( ARMOR );
|
||||
|
||||
ring1 = (Ring)bundle.get( RING1 );
|
||||
if (ring1 != null) {
|
||||
ring1.activate( owner );
|
||||
}
|
||||
|
||||
ring2 = (Ring)bundle.get( RING2 );
|
||||
if (ring2 != null) {
|
||||
ring2.activate( owner );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public<T extends Item> T getItem( Class<T> itemClass ) {
|
||||
|
||||
for (Item item : this) {
|
||||
if (itemClass.isInstance( item )) {
|
||||
return (T)item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Key> T getKey( Class<T> kind, int depth ) {
|
||||
|
||||
for (Item item : backpack) {
|
||||
if (item.getClass() == kind && ((Key)item).depth == depth) {
|
||||
return (T)item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void countIronKeys() {
|
||||
|
||||
IronKey.curDepthQunatity = 0;
|
||||
|
||||
for (Item item : backpack) {
|
||||
if (item instanceof IronKey && ((IronKey)item).depth == Dungeon.depth) {
|
||||
IronKey.curDepthQunatity = item.quantity();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void identify() {
|
||||
for (Item item : this) {
|
||||
item.identify();
|
||||
}
|
||||
}
|
||||
|
||||
public void observe() {
|
||||
if (weapon != null) {
|
||||
weapon.identify();
|
||||
Badges.validateItemLevelAquired( weapon );
|
||||
}
|
||||
if (armor != null) {
|
||||
armor.identify();
|
||||
Badges.validateItemLevelAquired( armor );
|
||||
}
|
||||
if (ring1 != null) {
|
||||
ring1.identify();
|
||||
Badges.validateItemLevelAquired( ring1 );
|
||||
}
|
||||
if (ring2 != null) {
|
||||
ring2.identify();
|
||||
Badges.validateItemLevelAquired( ring2 );
|
||||
}
|
||||
for (Item item : backpack) {
|
||||
item.cursedKnown = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void uncurseEquipped() {
|
||||
ScrollOfRemoveCurse.uncurse( owner, armor, weapon, ring1, ring2 );
|
||||
}
|
||||
|
||||
public Item randomUnequipped() {
|
||||
return Random.element( backpack.items );
|
||||
}
|
||||
|
||||
public void resurrect( int depth ) {
|
||||
|
||||
for (Item item : backpack.items.toArray( new Item[0])) {
|
||||
if (item instanceof Key) {
|
||||
if (((Key)item).depth == depth) {
|
||||
item.detachAll( backpack );
|
||||
}
|
||||
} else if (item.unique) {
|
||||
|
||||
} else if (!item.isEquipped( owner )) {
|
||||
item.detachAll( backpack );
|
||||
}
|
||||
}
|
||||
|
||||
if (weapon != null) {
|
||||
weapon.cursed = false;
|
||||
weapon.activate( owner );
|
||||
}
|
||||
|
||||
if (armor != null) {
|
||||
armor.cursed = false;
|
||||
}
|
||||
|
||||
if (ring1 != null) {
|
||||
ring1.cursed = false;
|
||||
ring1.activate( owner );
|
||||
}
|
||||
if (ring2 != null) {
|
||||
ring2.cursed = false;
|
||||
ring2.activate( owner );
|
||||
}
|
||||
}
|
||||
|
||||
public int charge( boolean full) {
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (Item item : this) {
|
||||
if (item instanceof Wand) {
|
||||
Wand wand = (Wand)item;
|
||||
if (wand.curCharges < wand.maxCharges) {
|
||||
wand.curCharges = full ? wand.maxCharges : wand.curCharges + 1;
|
||||
count++;
|
||||
|
||||
wand.updateQuickslot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public int discharge() {
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (Item item : this) {
|
||||
if (item instanceof Wand) {
|
||||
Wand wand = (Wand)item;
|
||||
if (wand.curCharges > 0) {
|
||||
wand.curCharges--;
|
||||
count++;
|
||||
|
||||
wand.updateQuickslot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Item> iterator() {
|
||||
return new ItemIterator();
|
||||
}
|
||||
|
||||
private class ItemIterator implements Iterator<Item> {
|
||||
|
||||
private int index = 0;
|
||||
|
||||
private Iterator<Item> backpackIterator = backpack.iterator();
|
||||
|
||||
private Item[] equipped = {weapon, armor, ring1, ring2};
|
||||
private int backpackIndex = equipped.length;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
|
||||
for (int i=index; i < backpackIndex; i++) {
|
||||
if (equipped[i] != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return backpackIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item next() {
|
||||
|
||||
while (index < backpackIndex) {
|
||||
Item item = equipped[index++];
|
||||
if (item != null) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return backpackIterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
switch (index) {
|
||||
case 0:
|
||||
equipped[0] = weapon = null;
|
||||
break;
|
||||
case 1:
|
||||
equipped[1] = armor = null;
|
||||
break;
|
||||
case 2:
|
||||
equipped[2] = ring1 = null;
|
||||
break;
|
||||
case 3:
|
||||
equipped[3] = ring2 = null;
|
||||
break;
|
||||
default:
|
||||
backpackIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.hero;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
|
||||
|
||||
public class HeroAction {
|
||||
|
||||
public int dst;
|
||||
|
||||
public static class Move extends HeroAction {
|
||||
public Move( int dst ) {
|
||||
this.dst = dst;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PickUp extends HeroAction {
|
||||
public PickUp( int dst ) {
|
||||
this.dst = dst;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OpenChest extends HeroAction {
|
||||
public OpenChest( int dst ) {
|
||||
this.dst = dst;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Buy extends HeroAction {
|
||||
public Buy( int dst ) {
|
||||
this.dst = dst;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Interact extends HeroAction {
|
||||
public Mob.NPC npc;
|
||||
public Interact( Mob.NPC npc ) {
|
||||
this.npc = npc;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Unlock extends HeroAction {
|
||||
public Unlock( int door ) {
|
||||
this.dst = door;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Descend extends HeroAction {
|
||||
public Descend( int stairs ) {
|
||||
this.dst = stairs;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Ascend extends HeroAction {
|
||||
public Ascend( int stairs ) {
|
||||
this.dst = stairs;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Cook extends HeroAction {
|
||||
public Cook( int pot ) {
|
||||
this.dst = pot;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Attack extends HeroAction {
|
||||
public Char target;
|
||||
public Attack( Char target ) {
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* 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.hero;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.TomeOfMastery;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClothArmor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.Food;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfShadows;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfIdentify;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMagicMapping;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dagger;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Knuckles;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.ShortSword;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Dart;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Boomerang;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public enum HeroClass {
|
||||
|
||||
WARRIOR( "warrior" ), MAGE( "mage" ), ROGUE( "rogue" ), HUNTRESS( "huntress" );
|
||||
|
||||
private String title;
|
||||
|
||||
private HeroClass( String title ) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public static final String[] WAR_PERKS = {
|
||||
"Warriors start with 11 points of Strength.",
|
||||
"Warriors start with a unique short sword. This sword can be later \"reforged\" to upgrade another melee weapon.",
|
||||
"Warriors are less proficient with missile weapons.",
|
||||
"Any piece of food restores some health when eaten.",
|
||||
"Potions of Strength are identified from the beginning.",
|
||||
};
|
||||
|
||||
public static final String[] MAG_PERKS = {
|
||||
"Mages start with a unique Wand of Magic Missile. This wand can be later \"disenchanted\" to upgrade another wand.",
|
||||
"Mages recharge their wands faster.",
|
||||
"When eaten, any piece of food restores 1 charge for all wands in the inventory.",
|
||||
"Mages can use wands as a melee weapon.",
|
||||
"Scrolls of Identify are identified from the beginning."
|
||||
};
|
||||
|
||||
public static final String[] ROG_PERKS = {
|
||||
"Rogues start with a Ring of Shadows+1.",
|
||||
"Rogues identify a type of a ring on equipping it.",
|
||||
"Rogues are proficient with light armor, dodging better while wearing one.",
|
||||
"Rogues are proficient in detecting hidden doors and traps.",
|
||||
"Rogues can go without food longer.",
|
||||
"Scrolls of Magic Mapping are identified from the beginning."
|
||||
};
|
||||
|
||||
public static final String[] HUN_PERKS = {
|
||||
"Huntresses start with 15 points of Health.",
|
||||
"Huntresses start with a unique upgradeable boomerang.",
|
||||
"Huntresses are proficient with missile weapons and get damage bonus for excessive strength when using them.",
|
||||
"Huntresses gain more health from dewdrops.",
|
||||
"Huntresses sense neighbouring monsters even if they are hidden behind obstacles."
|
||||
};
|
||||
|
||||
public void initHero( Hero hero ) {
|
||||
|
||||
hero.heroClass = this;
|
||||
|
||||
switch (this) {
|
||||
case WARRIOR:
|
||||
initWarrior( hero );
|
||||
break;
|
||||
|
||||
case MAGE:
|
||||
initMage( hero );
|
||||
break;
|
||||
|
||||
case ROGUE:
|
||||
initRogue( hero );
|
||||
break;
|
||||
|
||||
case HUNTRESS:
|
||||
initHuntress( hero );
|
||||
break;
|
||||
}
|
||||
|
||||
hero.updateAwareness();
|
||||
}
|
||||
|
||||
private static void initWarrior( Hero hero ) {
|
||||
hero.STR = hero.STR + 1;
|
||||
|
||||
(hero.belongings.weapon = new ShortSword()).identify();
|
||||
(hero.belongings.armor = new ClothArmor()).identify();
|
||||
new Dart( 8 ).identify().collect();
|
||||
new Food().identify().collect();
|
||||
|
||||
if (Badges.isUnlocked( Badges.Badge.MASTERY_WARRIOR )) {
|
||||
new TomeOfMastery().collect();
|
||||
}
|
||||
|
||||
Dungeon.quickslot = Dart.class;
|
||||
|
||||
new PotionOfStrength().setKnown();
|
||||
}
|
||||
|
||||
private static void initMage( Hero hero ) {
|
||||
(hero.belongings.weapon = new Knuckles()).identify();
|
||||
(hero.belongings.armor = new ClothArmor()).identify();
|
||||
new Food().identify().collect();
|
||||
|
||||
WandOfMagicMissile wand = new WandOfMagicMissile();
|
||||
wand.identify().collect();
|
||||
|
||||
if (Badges.isUnlocked( Badges.Badge.MASTERY_MAGE )) {
|
||||
new TomeOfMastery().collect();
|
||||
}
|
||||
|
||||
Dungeon.quickslot = wand;
|
||||
|
||||
new ScrollOfIdentify().setKnown();
|
||||
}
|
||||
|
||||
private static void initRogue( Hero hero ) {
|
||||
(hero.belongings.weapon = new Dagger()).identify();
|
||||
(hero.belongings.armor = new ClothArmor()).identify();
|
||||
(hero.belongings.ring1 = new RingOfShadows()).upgrade().identify();
|
||||
new Dart( 8 ).identify().collect();
|
||||
new Food().identify().collect();
|
||||
|
||||
hero.belongings.ring1.activate( hero );
|
||||
|
||||
if (Badges.isUnlocked( Badges.Badge.MASTERY_ROGUE )) {
|
||||
new TomeOfMastery().collect();
|
||||
}
|
||||
|
||||
Dungeon.quickslot = Dart.class;
|
||||
|
||||
new ScrollOfMagicMapping().setKnown();
|
||||
}
|
||||
|
||||
private static void initHuntress( Hero hero ) {
|
||||
|
||||
hero.HP = (hero.HT -= 5);
|
||||
|
||||
(hero.belongings.weapon = new Dagger()).identify();
|
||||
(hero.belongings.armor = new ClothArmor()).identify();
|
||||
Boomerang boomerang = new Boomerang();
|
||||
boomerang.identify().collect();
|
||||
new Food().identify().collect();
|
||||
|
||||
if (Badges.isUnlocked( Badges.Badge.MASTERY_HUNTRESS )) {
|
||||
new TomeOfMastery().collect();
|
||||
}
|
||||
|
||||
Dungeon.quickslot = boomerang;
|
||||
}
|
||||
|
||||
public String title() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String spritesheet() {
|
||||
|
||||
switch (this) {
|
||||
case WARRIOR:
|
||||
return Assets.WARRIOR;
|
||||
case MAGE:
|
||||
return Assets.MAGE;
|
||||
case ROGUE:
|
||||
return Assets.ROGUE;
|
||||
case HUNTRESS:
|
||||
return Assets.HUNTRESS;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] perks() {
|
||||
|
||||
switch (this) {
|
||||
case WARRIOR:
|
||||
return WAR_PERKS;
|
||||
case MAGE:
|
||||
return MAG_PERKS;
|
||||
case ROGUE:
|
||||
return ROG_PERKS;
|
||||
case HUNTRESS:
|
||||
return HUN_PERKS;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final String CLASS = "class";
|
||||
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( CLASS, toString() );
|
||||
}
|
||||
|
||||
public static HeroClass restoreInBundle( Bundle bundle ) {
|
||||
String value = bundle.getString( CLASS );
|
||||
return value.length() > 0 ? valueOf( value ) : ROGUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.hero;
|
||||
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
public enum HeroSubClass {
|
||||
|
||||
NONE( null, null ),
|
||||
|
||||
GLADIATOR( "gladiator",
|
||||
"A successful attack with a melee weapon allows the _Gladiator_ to start a combo, " +
|
||||
"in which every next successful hit inflicts more damage." ),
|
||||
|
||||
BERSERKER( "berserker",
|
||||
"When severely wounded, the _Berserker_ enters a state of wild fury " +
|
||||
"significantly increasing his damage output." ),
|
||||
|
||||
WARLOCK( "warlock",
|
||||
"After killing an enemy the _Warlock_ consumes its soul. " +
|
||||
"It heals his wounds and satisfies his hunger." ),
|
||||
|
||||
BATTLEMAGE( "battlemage",
|
||||
"When fighting with a wand in his hands, the _Battlemage_ inflicts additional damage depending " +
|
||||
"on the current number of charges. Every successful hit restores 1 charge to this wand." ),
|
||||
|
||||
ASSASSIN( "assassin",
|
||||
"When performing a surprise attack, the _Assassin_ inflicts additional damage to his target." ),
|
||||
|
||||
FREERUNNER( "freerunner",
|
||||
"The _Freerunner_ can move almost twice faster, than most of the monsters. When he " +
|
||||
"is running, the Freerunner is much harder to hit. For that he must be unencumbered and not starving." ),
|
||||
|
||||
SNIPER( "sniper",
|
||||
"_Snipers_ are able to detect weak points in an enemy's armor, " +
|
||||
"effectively ignoring it when using a missile weapon." ),
|
||||
|
||||
WARDEN( "warden",
|
||||
"Having a strong connection with forces of nature gives _Wardens_ an ability to gather dewdrops and " +
|
||||
"seeds from plants. Also trampling a high grass grants them a temporary armor buff." );
|
||||
|
||||
private String title;
|
||||
private String desc;
|
||||
|
||||
private HeroSubClass( String title, String desc ) {
|
||||
this.title = title;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String title() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String desc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
private static final String SUBCLASS = "subClass";
|
||||
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( SUBCLASS, toString() );
|
||||
}
|
||||
|
||||
public static HeroSubClass restoreInBundle( Bundle bundle ) {
|
||||
String value = bundle.getString( SUBCLASS );
|
||||
try {
|
||||
return valueOf( value );
|
||||
} catch (Exception e) {
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.AcidicSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Acidic extends Scorpio {
|
||||
|
||||
{
|
||||
name = "acidic scorpio";
|
||||
spriteClass = AcidicSprite.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseProc( Char enemy, int damage ) {
|
||||
|
||||
int dmg = Random.IntRange( 0, damage );
|
||||
if (dmg > 0) {
|
||||
enemy.damage( dmg, this );
|
||||
}
|
||||
|
||||
return super.defenseProc( enemy, damage );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
Badges.validateRare( this );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.AlbinoSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Albino extends Rat {
|
||||
|
||||
{
|
||||
name = "albino rat";
|
||||
spriteClass = AlbinoSprite.class;
|
||||
|
||||
HP = HT = 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
Badges.validateRare( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
Buff.affect( enemy, Bleeding.class ).set( damage );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.BanditSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Bandit extends Thief {
|
||||
|
||||
public Item item;
|
||||
|
||||
{
|
||||
name = "crazy bandit";
|
||||
spriteClass = BanditSprite.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean steal( Hero hero ) {
|
||||
if (super.steal( hero )) {
|
||||
|
||||
Buff.prolong( enemy, Blindness.class, Random.Int( 5, 12 ) );
|
||||
Dungeon.observe();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
Badges.validateRare( this );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Leech;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.BatSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Bat extends Mob {
|
||||
|
||||
{
|
||||
name = "vampire bat";
|
||||
spriteClass = BatSprite.class;
|
||||
|
||||
HP = HT = 30;
|
||||
defenseSkill = 15;
|
||||
baseSpeed = 2f;
|
||||
|
||||
EXP = 7;
|
||||
maxLvl = 15;
|
||||
|
||||
flying = true;
|
||||
|
||||
loot = new PotionOfHealing();
|
||||
lootChance = 0.125f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 6, 12 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "evaded";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
|
||||
int reg = Math.min( damage, HT - HP );
|
||||
|
||||
if (reg > 0) {
|
||||
HP += reg;
|
||||
sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"These brisk and tenacious inhabitants of cave domes may defeat much larger opponents by " +
|
||||
"replenishing their health with each successful attack.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( Leech.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Bestiary {
|
||||
|
||||
public static Mob mob( int depth ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Mob> cl = (Class<? extends Mob>)mobClass( depth );
|
||||
try {
|
||||
return cl.newInstance();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Mob mutable( int depth ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Mob> cl = (Class<? extends Mob>)mobClass( depth );
|
||||
|
||||
if (Random.Int( 30 ) == 0) {
|
||||
if (cl == Rat.class) {
|
||||
cl = Albino.class;
|
||||
} else if (cl == Thief.class) {
|
||||
cl = Bandit.class;
|
||||
} else if (cl == Brute.class) {
|
||||
cl = Shielded.class;
|
||||
} else if (cl == Monk.class) {
|
||||
cl = Senior.class;
|
||||
} else if (cl == Scorpio.class) {
|
||||
cl = Acidic.class;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return cl.newInstance();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> mobClass( int depth ) {
|
||||
|
||||
float[] chances;
|
||||
Class<?>[] classes;
|
||||
|
||||
switch (depth) {
|
||||
case 1:
|
||||
chances = new float[]{ 1 };
|
||||
classes = new Class<?>[]{ Rat.class };
|
||||
break;
|
||||
case 2:
|
||||
chances = new float[]{ 1, 1 };
|
||||
classes = new Class<?>[]{ Rat.class, Gnoll.class };
|
||||
break;
|
||||
case 3:
|
||||
chances = new float[]{ 1, 2, 1, 0.02f };
|
||||
classes = new Class<?>[]{ Rat.class, Gnoll.class, Crab.class, Swarm.class };
|
||||
break;
|
||||
case 4:
|
||||
chances = new float[]{ 1, 2, 3, 0.02f, 0.01f, 0.01f };
|
||||
classes = new Class<?>[]{ Rat.class, Gnoll.class, Crab.class, Swarm.class, Skeleton.class, Thief.class };
|
||||
break;
|
||||
|
||||
case 5:
|
||||
chances = new float[]{ 1 };
|
||||
classes = new Class<?>[]{ Goo.class };
|
||||
break;
|
||||
|
||||
case 6:
|
||||
chances = new float[]{ 4, 2, 1, 0.2f };
|
||||
classes = new Class<?>[]{ Skeleton.class, Thief.class, Swarm.class, Shaman.class };
|
||||
break;
|
||||
case 7:
|
||||
chances = new float[]{ 3, 1, 1, 1 };
|
||||
classes = new Class<?>[]{ Skeleton.class, Shaman.class, Thief.class, Swarm.class };
|
||||
break;
|
||||
case 8:
|
||||
chances = new float[]{ 3, 2, 1, 1, 1, 0.02f };
|
||||
classes = new Class<?>[]{ Skeleton.class, Shaman.class, Gnoll.class, Thief.class, Swarm.class, Bat.class };
|
||||
break;
|
||||
case 9:
|
||||
chances = new float[]{ 3, 3, 1, 1, 0.02f, 0.01f };
|
||||
classes = new Class<?>[]{ Skeleton.class, Shaman.class, Thief.class, Swarm.class, Bat.class, Brute.class };
|
||||
break;
|
||||
|
||||
case 10:
|
||||
chances = new float[]{ 1 };
|
||||
classes = new Class<?>[]{ Tengu.class };
|
||||
break;
|
||||
|
||||
case 11:
|
||||
chances = new float[]{ 1, 0.2f };
|
||||
classes = new Class<?>[]{ Bat.class, Brute.class };
|
||||
break;
|
||||
case 12:
|
||||
chances = new float[]{ 1, 1, 0.2f };
|
||||
classes = new Class<?>[]{ Bat.class, Brute.class, Spinner.class };
|
||||
break;
|
||||
case 13:
|
||||
chances = new float[]{ 1, 3, 1, 1, 0.02f };
|
||||
classes = new Class<?>[]{ Bat.class, Brute.class, Shaman.class, Spinner.class, Elemental.class };
|
||||
break;
|
||||
case 14:
|
||||
chances = new float[]{ 1, 3, 1, 4, 0.02f, 0.01f };
|
||||
classes = new Class<?>[]{ Bat.class, Brute.class, Shaman.class, Spinner.class, Elemental.class, Monk.class };
|
||||
break;
|
||||
|
||||
case 15:
|
||||
chances = new float[]{ 1 };
|
||||
classes = new Class<?>[]{ DM300.class };
|
||||
break;
|
||||
|
||||
case 16:
|
||||
chances = new float[]{ 1, 1, 0.2f };
|
||||
classes = new Class<?>[]{ Elemental.class, Warlock.class, Monk.class };
|
||||
break;
|
||||
case 17:
|
||||
chances = new float[]{ 1, 1, 1 };
|
||||
classes = new Class<?>[]{ Elemental.class, Monk.class, Warlock.class };
|
||||
break;
|
||||
case 18:
|
||||
chances = new float[]{ 1, 2, 1, 1 };
|
||||
classes = new Class<?>[]{ Elemental.class, Monk.class, Golem.class, Warlock.class };
|
||||
break;
|
||||
case 19:
|
||||
chances = new float[]{ 1, 2, 3, 1, 0.02f };
|
||||
classes = new Class<?>[]{ Elemental.class, Monk.class, Golem.class, Warlock.class, Succubus.class };
|
||||
break;
|
||||
|
||||
case 20:
|
||||
chances = new float[]{ 1 };
|
||||
classes = new Class<?>[]{ King.class };
|
||||
break;
|
||||
|
||||
case 22:
|
||||
chances = new float[]{ 1, 1 };
|
||||
classes = new Class<?>[]{ Succubus.class, Eye.class };
|
||||
break;
|
||||
case 23:
|
||||
chances = new float[]{ 1, 2, 1 };
|
||||
classes = new Class<?>[]{ Succubus.class, Eye.class, Scorpio.class };
|
||||
break;
|
||||
case 24:
|
||||
chances = new float[]{ 1, 2, 3 };
|
||||
classes = new Class<?>[]{ Succubus.class, Eye.class, Scorpio.class };
|
||||
break;
|
||||
|
||||
case 25:
|
||||
chances = new float[]{ 1 };
|
||||
classes = new Class<?>[]{ Yog.class };
|
||||
break;
|
||||
|
||||
default:
|
||||
chances = new float[]{ 1 };
|
||||
classes = new Class<?>[]{ Eye.class };
|
||||
}
|
||||
|
||||
return classes[ Random.chances( chances )];
|
||||
}
|
||||
|
||||
public static boolean isUnique( Char mob ) {
|
||||
return mob instanceof Goo || mob instanceof Tengu || mob instanceof DM300 || mob instanceof King || mob instanceof Yog;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.BruteSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Brute extends Mob {
|
||||
|
||||
private static final String TXT_ENRAGED = "%s becomes enraged!";
|
||||
|
||||
{
|
||||
name = "gnoll brute";
|
||||
spriteClass = BruteSprite.class;
|
||||
|
||||
HP = HT = 40;
|
||||
defenseSkill = 15;
|
||||
|
||||
EXP = 8;
|
||||
maxLvl = 15;
|
||||
|
||||
loot = Gold.class;
|
||||
lootChance = 0.5f;
|
||||
}
|
||||
|
||||
private boolean enraged = false;
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
enraged = HP < HT / 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return enraged ?
|
||||
Random.NormalIntRange( 10, 40 ) :
|
||||
Random.NormalIntRange( 8, 18 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
super.damage( dmg, src );
|
||||
|
||||
if (isAlive() && !enraged && HP < HT / 4) {
|
||||
enraged = true;
|
||||
spend( TICK );
|
||||
if (Dungeon.visible[pos]) {
|
||||
GLog.w( TXT_ENRAGED, name );
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "enraged" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Brutes are the largest, strongest and toughest of all gnolls. When severely wounded, " +
|
||||
"they go berserk, inflicting even more damage to their enemies.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Terror.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CrabSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Crab extends Mob {
|
||||
|
||||
{
|
||||
name = "sewer crab";
|
||||
spriteClass = CrabSprite.class;
|
||||
|
||||
HP = HT = 15;
|
||||
defenseSkill = 5;
|
||||
baseSpeed = 2f;
|
||||
|
||||
EXP = 3;
|
||||
maxLvl = 9;
|
||||
|
||||
loot = new MysteryMeat();
|
||||
lootChance = 0.167f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 3, 6 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "parried";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
Ghost.Quest.process( pos );
|
||||
super.die( cause );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"These huge crabs are at the top of the food chain in the sewers. " +
|
||||
"They are extremely fast and their thick exoskeleton can withstand " +
|
||||
"heavy blows.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.Camera;
|
||||
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.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.Paralysis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ElmoParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfThorns;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.DM300Sprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class DM300 extends Mob {
|
||||
|
||||
{
|
||||
name = "DM-300";
|
||||
spriteClass = DM300Sprite.class;
|
||||
|
||||
HP = HT = 200;
|
||||
EXP = 30;
|
||||
defenseSkill = 18;
|
||||
|
||||
loot = new RingOfThorns().random();
|
||||
lootChance = 0.333f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 18, 24 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 28;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
|
||||
GameScene.add( Blob.seed( pos, 30, ToxicGas.class ) );
|
||||
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move( int step ) {
|
||||
super.move( step );
|
||||
|
||||
if (Dungeon.level.map[step] == Terrain.INACTIVE_TRAP && HP < HT) {
|
||||
|
||||
HP += Random.Int( 1, HT - HP );
|
||||
sprite.emitter().burst( ElmoParticle.FACTORY, 5 );
|
||||
|
||||
if (Dungeon.visible[step] && Dungeon.hero.isAlive()) {
|
||||
GLog.n( "DM-300 repairs itself!" );
|
||||
}
|
||||
}
|
||||
|
||||
int[] cells = {
|
||||
step-1, step+1, step-Level.WIDTH, step+Level.WIDTH,
|
||||
step-1-Level.WIDTH,
|
||||
step-1+Level.WIDTH,
|
||||
step+1-Level.WIDTH,
|
||||
step+1+Level.WIDTH
|
||||
};
|
||||
int cell = cells[Random.Int( cells.length )];
|
||||
|
||||
if (Dungeon.visible[cell]) {
|
||||
CellEmitter.get( cell ).start( Speck.factory( Speck.ROCK ), 0.07f, 10 );
|
||||
Camera.main.shake( 3, 0.7f );
|
||||
Sample.INSTANCE.play( Assets.SND_ROCKS );
|
||||
|
||||
if (Level.water[cell]) {
|
||||
GameScene.ripple( cell );
|
||||
} else if (Dungeon.level.map[cell] == Terrain.EMPTY) {
|
||||
Level.set( cell, Terrain.EMPTY_DECO );
|
||||
GameScene.updateMap( cell );
|
||||
}
|
||||
}
|
||||
|
||||
Char ch = Actor.findChar( cell );
|
||||
if (ch != null && ch != this) {
|
||||
Buff.prolong( ch, Paralysis.class, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
|
||||
super.die( cause );
|
||||
|
||||
GameScene.bossSlain();
|
||||
Dungeon.level.drop( new SkeletonKey( Dungeon.depth ), pos ).sprite.drop();
|
||||
|
||||
Badges.validateBossSlain();
|
||||
|
||||
yell( "Mission failed. Shutting down." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notice() {
|
||||
super.notice();
|
||||
yell( "Unauthorised personnel detected." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"This machine was created by the Dwarves several centuries ago. Later, Dwarves started to replace machines with " +
|
||||
"golems, elementals and even demons. Eventually it led their civilization to the decline. The DM-300 and similar " +
|
||||
"machines were typically used for construction and mining, and in some cases, for city defense.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( Death.class );
|
||||
RESISTANCES.add( ScrollOfPsionicBlast.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( ToxicGas.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfLiquidFlame;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFirebolt;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Fire;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ElementalSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Elemental extends Mob {
|
||||
|
||||
{
|
||||
name = "fire elemental";
|
||||
spriteClass = ElementalSprite.class;
|
||||
|
||||
HP = HT = 65;
|
||||
defenseSkill = 20;
|
||||
|
||||
EXP = 10;
|
||||
maxLvl = 20;
|
||||
|
||||
flying = true;
|
||||
|
||||
loot = new PotionOfLiquidFlame();
|
||||
lootChance = 0.1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 16, 20 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 25;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
Buff.affect( enemy, Burning.class ).reignite( enemy );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( Buff buff ) {
|
||||
if (buff instanceof Burning) {
|
||||
if (HP < HT) {
|
||||
HP++;
|
||||
sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 );
|
||||
}
|
||||
} else {
|
||||
if (buff instanceof Frost) {
|
||||
damage( Random.NormalIntRange( 1, HT * 2 / 3 ), buff );
|
||||
}
|
||||
super.add( buff );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Wandering fire elementals are a byproduct of summoning greater entities. " +
|
||||
"They are too chaotic in their nature to be controlled by even the most powerful demonologist.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Burning.class );
|
||||
IMMUNITIES.add( Fire.class );
|
||||
IMMUNITIES.add( WandOfFirebolt.class );
|
||||
IMMUNITIES.add( ScrollOfPsionicBlast.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PurpleParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Dewdrop;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfDisintegration;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Leech;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.EyeSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Eye extends Mob {
|
||||
|
||||
private static final String TXT_DEATHGAZE_KILLED = "%s's deathgaze killed you...";
|
||||
|
||||
{
|
||||
name = "evil eye";
|
||||
spriteClass = EyeSprite.class;
|
||||
|
||||
HP = HT = 100;
|
||||
defenseSkill = 20;
|
||||
viewDistance = Light.DISTANCE;
|
||||
|
||||
EXP = 13;
|
||||
maxLvl = 25;
|
||||
|
||||
flying = true;
|
||||
|
||||
loot = new Dewdrop();
|
||||
lootChance = 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
private int hitCell;
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
|
||||
hitCell = Ballistica.cast( pos, enemy.pos, true, false );
|
||||
|
||||
for (int i=1; i < Ballistica.distance; i++) {
|
||||
if (Ballistica.trace[i] == enemy.pos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float attackDelay() {
|
||||
return 1.6f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doAttack( Char enemy ) {
|
||||
|
||||
spend( attackDelay() );
|
||||
|
||||
boolean rayVisible = false;
|
||||
|
||||
for (int i=0; i < Ballistica.distance; i++) {
|
||||
if (Dungeon.visible[Ballistica.trace[i]]) {
|
||||
rayVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rayVisible) {
|
||||
sprite.attack( hitCell );
|
||||
return false;
|
||||
} else {
|
||||
attack( enemy );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean attack( Char enemy ) {
|
||||
|
||||
for (int i=1; i < Ballistica.distance; i++) {
|
||||
|
||||
int pos = Ballistica.trace[i];
|
||||
|
||||
Char ch = Actor.findChar( pos );
|
||||
if (ch == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hit( this, ch, true )) {
|
||||
ch.damage( Random.NormalIntRange( 14, 20 ), this );
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
ch.sprite.flash();
|
||||
CellEmitter.center( pos ).burst( PurpleParticle.BURST, Random.IntRange( 1, 2 ) );
|
||||
}
|
||||
|
||||
if (!ch.isAlive() && ch == Dungeon.hero) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.MOB, Utils.indefinite( name ), Dungeon.depth ) );
|
||||
GLog.n( TXT_DEATHGAZE_KILLED, name );
|
||||
}
|
||||
} else {
|
||||
ch.sprite.showStatus( CharSprite.NEUTRAL, ch.defenseVerb() );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"One of this demon's other names is \"orb of hatred\", because when it sees an enemy, " +
|
||||
"it uses its deathgaze recklessly, often ignoring its allies and wounding them.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( WandOfDisintegration.class );
|
||||
RESISTANCES.add( Death.class );
|
||||
RESISTANCES.add( Leech.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Terror.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.GnollSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Gnoll extends Mob {
|
||||
|
||||
{
|
||||
name = "gnoll scout";
|
||||
spriteClass = GnollSprite.class;
|
||||
|
||||
HP = HT = 12;
|
||||
defenseSkill = 4;
|
||||
|
||||
EXP = 2;
|
||||
maxLvl = 8;
|
||||
|
||||
loot = Gold.class;
|
||||
lootChance = 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 2, 5 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 11;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
Ghost.Quest.process( pos );
|
||||
super.die( cause );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Gnolls are hyena-like humanoids. They dwell in sewers and dungeons, venturing up to raid the surface from time to time. " +
|
||||
"Gnoll scouts are regular members of their pack, they are not as strong as brutes and not as intelligent as shamans.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.GolemSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Golem extends Mob {
|
||||
|
||||
{
|
||||
name = "golem";
|
||||
spriteClass = GolemSprite.class;
|
||||
|
||||
HP = HT = 85;
|
||||
defenseSkill = 18;
|
||||
|
||||
EXP = 12;
|
||||
maxLvl = 22;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 20, 40 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 28;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float attackDelay() {
|
||||
return 1.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "blocked";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
Imp.Quest.process( this );
|
||||
|
||||
super.die( cause );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"The Dwarves tried to combine their knowledge of mechanisms with their newfound power of elemental binding. " +
|
||||
"They used spirits of earth as the \"soul\" for the mechanical bodies of golems, which were believed to be " +
|
||||
"most controllable of all. Despite this, the tiniest mistake in the ritual could cause an outbreak.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( ScrollOfPsionicBlast.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Amok.class );
|
||||
IMMUNITIES.add( Terror.class );
|
||||
IMMUNITIES.add( Sleep.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.Camera;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
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.Ooze;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.LloydsBeacon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.SewerBossLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.GooSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Goo extends Mob {
|
||||
|
||||
private static final float PUMP_UP_DELAY = 2f;
|
||||
|
||||
{
|
||||
name = "Goo";
|
||||
HP = HT = 80;
|
||||
EXP = 10;
|
||||
defenseSkill = 12;
|
||||
spriteClass = GooSprite.class;
|
||||
|
||||
loot = new LloydsBeacon();
|
||||
lootChance = 0.333f;
|
||||
}
|
||||
|
||||
private boolean pumpedUp = false;
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
if (pumpedUp) {
|
||||
return Random.NormalIntRange( 5, 30 );
|
||||
} else {
|
||||
return Random.NormalIntRange( 2, 12 );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return pumpedUp ? 30 : 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
|
||||
if (Level.water[pos] && HP < HT) {
|
||||
sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 );
|
||||
HP++;
|
||||
}
|
||||
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return pumpedUp ? distance( enemy ) <= 2 : super.canAttack(enemy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (Random.Int( 3 ) == 0) {
|
||||
Buff.affect( enemy, Ooze.class );
|
||||
enemy.sprite.burst( 0x000000, 5 );
|
||||
}
|
||||
|
||||
if (pumpedUp) {
|
||||
Camera.main.shake( 3, 0.2f );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doAttack( Char enemy ) {
|
||||
if (pumpedUp || Random.Int( 3 ) > 0) {
|
||||
|
||||
return super.doAttack( enemy );
|
||||
|
||||
} else {
|
||||
|
||||
pumpedUp = true;
|
||||
spend( PUMP_UP_DELAY );
|
||||
|
||||
((GooSprite)sprite).pumpUp();
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
sprite.showStatus( CharSprite.NEGATIVE, "!!!" );
|
||||
GLog.n( "Goo is pumping itself up!" );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean attack( Char enemy ) {
|
||||
boolean result = super.attack( enemy );
|
||||
pumpedUp = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getCloser( int target ) {
|
||||
pumpedUp = false;
|
||||
return super.getCloser( target );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move( int step ) {
|
||||
((SewerBossLevel)Dungeon.level).seal();
|
||||
super.move( step );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
|
||||
super.die( cause );
|
||||
|
||||
((SewerBossLevel)Dungeon.level).unseal();
|
||||
|
||||
GameScene.bossSlain();
|
||||
Dungeon.level.drop( new SkeletonKey( Dungeon.depth ), pos ).sprite.drop();
|
||||
|
||||
Badges.validateBossSlain();
|
||||
|
||||
yell( "glurp... glurp..." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notice() {
|
||||
super.notice();
|
||||
yell( "GLURP-GLURP!" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Little known about The Goo. It's quite possible that it is not even a creature, but rather a " +
|
||||
"conglomerate of substances from the sewers that gained rudiments of free will.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( ToxicGas.class );
|
||||
RESISTANCES.add( Death.class );
|
||||
RESISTANCES.add( ScrollOfPsionicBlast.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
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.actors.Actor;
|
||||
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.Paralysis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.ArmorKit;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfDisintegration;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.CityBossLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.KingSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.UndeadSprite;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.PathFinder;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class King extends Mob {
|
||||
|
||||
private static final int MAX_ARMY_SIZE = 5;
|
||||
|
||||
{
|
||||
name = "King of Dwarves";
|
||||
spriteClass = KingSprite.class;
|
||||
|
||||
HP = HT = 300;
|
||||
EXP = 40;
|
||||
defenseSkill = 25;
|
||||
|
||||
Undead.count = 0;
|
||||
}
|
||||
|
||||
private boolean nextPedestal = true;
|
||||
|
||||
private static final String PEDESTAL = "pedestal";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( PEDESTAL, nextPedestal );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
nextPedestal = bundle.getBoolean( PEDESTAL );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 20, 38 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 14;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "parried";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getCloser( int target ) {
|
||||
return canTryToSummon() ?
|
||||
super.getCloser( CityBossLevel.pedestal( nextPedestal ) ) :
|
||||
super.getCloser( target );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return canTryToSummon() ?
|
||||
pos == CityBossLevel.pedestal( nextPedestal ) :
|
||||
Level.adjacent( pos, enemy.pos );
|
||||
}
|
||||
|
||||
private boolean canTryToSummon() {
|
||||
if (Undead.count < maxArmySize()) {
|
||||
Char ch = Actor.findChar( CityBossLevel.pedestal( nextPedestal ) );
|
||||
return ch == this || ch == null;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean attack( Char enemy ) {
|
||||
if (canTryToSummon() && pos == CityBossLevel.pedestal( nextPedestal )) {
|
||||
summon();
|
||||
return true;
|
||||
} else {
|
||||
if (Actor.findChar( CityBossLevel.pedestal( nextPedestal ) ) == enemy) {
|
||||
nextPedestal = !nextPedestal;
|
||||
}
|
||||
return super.attack(enemy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
|
||||
GameScene.bossSlain();
|
||||
Dungeon.level.drop( new ArmorKit(), pos ).sprite.drop();
|
||||
Dungeon.level.drop( new SkeletonKey( Dungeon.depth ), pos ).sprite.drop();
|
||||
|
||||
super.die( cause );
|
||||
|
||||
Badges.validateBossSlain();
|
||||
|
||||
yell( "You cannot kill me, " + Dungeon.hero.heroClass.title() + "... I am... immortal..." );
|
||||
}
|
||||
|
||||
private int maxArmySize() {
|
||||
return 1 + MAX_ARMY_SIZE * (HT - HP) / HT;
|
||||
}
|
||||
|
||||
private void summon() {
|
||||
|
||||
nextPedestal = !nextPedestal;
|
||||
|
||||
sprite.centerEmitter().start( Speck.factory( Speck.SCREAM ), 0.4f, 2 );
|
||||
Sample.INSTANCE.play( Assets.SND_CHALLENGE );
|
||||
|
||||
boolean[] passable = Level.passable.clone();
|
||||
for (Actor actor : Actor.all()) {
|
||||
if (actor instanceof Char) {
|
||||
passable[((Char)actor).pos] = false;
|
||||
}
|
||||
}
|
||||
|
||||
int undeadsToSummon = maxArmySize() - Undead.count;
|
||||
|
||||
PathFinder.buildDistanceMap( pos, passable, undeadsToSummon );
|
||||
PathFinder.distance[pos] = Integer.MAX_VALUE;
|
||||
int dist = 1;
|
||||
|
||||
undeadLabel:
|
||||
for (int i=0; i < undeadsToSummon; i++) {
|
||||
do {
|
||||
for (int j=0; j < Level.LENGTH; j++) {
|
||||
if (PathFinder.distance[j] == dist) {
|
||||
|
||||
Undead undead = new Undead();
|
||||
undead.pos = j;
|
||||
GameScene.add( undead );
|
||||
|
||||
WandOfBlink.appear( undead, j );
|
||||
new Flare( 3, 32 ).color( 0x000000, false ).show( undead.sprite, 2f ) ;
|
||||
|
||||
PathFinder.distance[j] = Integer.MAX_VALUE;
|
||||
|
||||
continue undeadLabel;
|
||||
}
|
||||
}
|
||||
dist++;
|
||||
} while (dist < undeadsToSummon);
|
||||
}
|
||||
|
||||
yell( "Arise, slaves!" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notice() {
|
||||
super.notice();
|
||||
yell( "How dare you!" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"The last king of dwarves was known for his deep understanding of processes of life and death. " +
|
||||
"He has persuaded members of his court to participate in a ritual, that should have granted them " +
|
||||
"eternal youthfulness. In the end he was the only one, who got it - and an army of undead " +
|
||||
"as a bonus.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( ToxicGas.class );
|
||||
RESISTANCES.add( Death.class );
|
||||
RESISTANCES.add( ScrollOfPsionicBlast.class );
|
||||
RESISTANCES.add( WandOfDisintegration.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Paralysis.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
|
||||
public static class Undead extends Mob {
|
||||
|
||||
public static int count = 0;
|
||||
|
||||
{
|
||||
name = "undead dwarf";
|
||||
spriteClass = UndeadSprite.class;
|
||||
|
||||
HP = HT = 28;
|
||||
defenseSkill = 15;
|
||||
|
||||
EXP = 0;
|
||||
|
||||
state = State.WANDERING;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAdd() {
|
||||
count++;
|
||||
super.onAdd();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove() {
|
||||
count--;
|
||||
super.onRemove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 12, 16 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (Random.Int( MAX_ARMY_SIZE ) == 0) {
|
||||
Buff.prolong( enemy, Paralysis.class, 1 );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
super.damage( dmg, src );
|
||||
if (src instanceof ToxicGas) {
|
||||
((ToxicGas)src).clear( pos );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
Sample.INSTANCE.play( Assets.SND_BONES );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "blocked";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"These undead dwarves, risen by the will of the King of Dwarves, were members of his court. " +
|
||||
"They appear as skeletons with a stunning amount of facial hair.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Death.class );
|
||||
IMMUNITIES.add( Paralysis.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,528 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Wound;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public abstract class Mob extends Char {
|
||||
|
||||
private static final String TXT_DIED = "You hear something died in the distance";
|
||||
|
||||
protected static final String TXT_NOTICE1 = "?!";
|
||||
protected static final String TXT_RAGE = "#$%^";
|
||||
protected static final String TXT_EXP = "%+dEXP";
|
||||
|
||||
public enum State {
|
||||
SLEEPING,
|
||||
HUNTING,
|
||||
WANDERING,
|
||||
FLEEING,
|
||||
PASSIVE
|
||||
}
|
||||
public State state = State.SLEEPING;
|
||||
|
||||
public Class<? extends CharSprite> spriteClass;
|
||||
|
||||
protected int target = -1;
|
||||
|
||||
protected int defenseSkill = 0;
|
||||
|
||||
protected int EXP = 1;
|
||||
protected int maxLvl = 30;
|
||||
|
||||
protected Char enemy;
|
||||
protected boolean enemySeen;
|
||||
protected boolean alerted = false;
|
||||
|
||||
protected static final float TIME_TO_WAKE_UP = 1f;
|
||||
|
||||
public boolean hostile = true;
|
||||
|
||||
// Unreachable target
|
||||
public static final Mob DUMMY = new Mob() {
|
||||
{
|
||||
pos = -1;
|
||||
}
|
||||
};
|
||||
|
||||
private static final String STATE = "state";
|
||||
private static final String TARGET = "target";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
|
||||
super.storeInBundle( bundle );
|
||||
|
||||
bundle.put( STATE, state.toString() );
|
||||
if (state != State.SLEEPING) {
|
||||
bundle.put( TARGET, target );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
super.restoreFromBundle( bundle );
|
||||
|
||||
state = State.valueOf( bundle.getString( STATE ) );
|
||||
if (state != State.SLEEPING) {
|
||||
target = bundle.getInt( TARGET );
|
||||
}
|
||||
}
|
||||
|
||||
public CharSprite sprite() {
|
||||
CharSprite sprite = null;
|
||||
try {
|
||||
sprite = spriteClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return sprite;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
|
||||
super.act();
|
||||
|
||||
boolean alertedNow = alerted;
|
||||
alerted = false;
|
||||
|
||||
sprite.hideAlert();
|
||||
|
||||
if (paralysed) {
|
||||
enemySeen = false;
|
||||
spend( TICK );
|
||||
return true;
|
||||
}
|
||||
|
||||
enemy = chooseEnemy();
|
||||
|
||||
boolean enemyInFOV = enemy.isAlive() && Level.fieldOfView[enemy.pos] && enemy.invisible <= 0;
|
||||
|
||||
int oldPos = pos;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case SLEEPING:
|
||||
if (enemyInFOV &&
|
||||
Random.Int( distance( enemy ) + enemy.stealth() + (enemy.flying ? 2 : 0) ) == 0) {
|
||||
|
||||
enemySeen = true;
|
||||
|
||||
notice();
|
||||
state = State.HUNTING;
|
||||
target = enemy.pos;
|
||||
|
||||
spend( TIME_TO_WAKE_UP );
|
||||
|
||||
} else {
|
||||
|
||||
enemySeen = false;
|
||||
|
||||
spend( TICK );
|
||||
|
||||
}
|
||||
return true;
|
||||
|
||||
case WANDERING:
|
||||
if (enemyInFOV && (alertedNow || Random.Int( distance( enemy ) / 2 + enemy.stealth() ) == 0)) {
|
||||
|
||||
enemySeen = true;
|
||||
|
||||
notice();
|
||||
state = State.HUNTING;
|
||||
target = enemy.pos;
|
||||
|
||||
} else {
|
||||
|
||||
enemySeen = false;
|
||||
|
||||
if (target != -1 && getCloser( target )) {
|
||||
spend( 1 / speed() );
|
||||
return moveSprite( oldPos, pos );
|
||||
} else {
|
||||
target = Dungeon.level.randomDestination();
|
||||
spend( TICK );
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
|
||||
case HUNTING:
|
||||
enemySeen = enemyInFOV;
|
||||
if (enemyInFOV && canAttack( enemy )) {
|
||||
|
||||
return doAttack( enemy );
|
||||
|
||||
} else {
|
||||
|
||||
if (enemyInFOV) {
|
||||
target = enemy.pos;
|
||||
}
|
||||
|
||||
if (target != -1 && getCloser( target )) {
|
||||
|
||||
|
||||
spend( 1 / speed() );
|
||||
return moveSprite( oldPos, pos );
|
||||
|
||||
} else {
|
||||
|
||||
spend( TICK );
|
||||
state = State.WANDERING;
|
||||
target = Dungeon.level.randomDestination(); // <--------
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
case FLEEING:
|
||||
enemySeen = enemyInFOV;
|
||||
if (enemyInFOV) {
|
||||
target = enemy.pos;
|
||||
}
|
||||
if (target != -1 && getFurther( target )) {
|
||||
|
||||
spend( 1 / speed() );
|
||||
return moveSprite( oldPos, pos );
|
||||
|
||||
} else {
|
||||
|
||||
spend( TICK );
|
||||
nowhereToRun();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case PASSIVE:
|
||||
enemySeen = false;
|
||||
spend( TICK );
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
protected Char chooseEnemy() {
|
||||
|
||||
if (buff( Amok.class ) != null) {
|
||||
if (enemy == Dungeon.hero || enemy == null) {
|
||||
|
||||
HashSet<Mob> enemies = new HashSet<Mob>();
|
||||
for (Mob mob:Dungeon.level.mobs) {
|
||||
if (mob != this && Level.fieldOfView[mob.pos]) {
|
||||
enemies.add( mob );
|
||||
}
|
||||
}
|
||||
if (enemies.size() > 0) {
|
||||
return Random.element( enemies );
|
||||
}
|
||||
|
||||
} else {
|
||||
return enemy;
|
||||
}
|
||||
}
|
||||
|
||||
Terror terror = (Terror)buff( Terror.class );
|
||||
if (terror != null) {
|
||||
return terror.source;
|
||||
}
|
||||
|
||||
return Dungeon.hero;
|
||||
}
|
||||
|
||||
protected void nowhereToRun() {
|
||||
}
|
||||
|
||||
protected boolean moveSprite( int from, int to ) {
|
||||
|
||||
if (sprite.isVisible() && (Dungeon.visible[from] || Dungeon.visible[to])) {
|
||||
sprite.move( from, to );
|
||||
return false;
|
||||
} else {
|
||||
sprite.place( to );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( Buff buff ) {
|
||||
super.add( buff );
|
||||
if (buff instanceof Amok) {
|
||||
if (sprite != null) {
|
||||
sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE );
|
||||
}
|
||||
state = State.HUNTING;
|
||||
} else if (buff instanceof Terror) {
|
||||
state = State.FLEEING;
|
||||
} else if (buff instanceof Sleep) {
|
||||
if (sprite != null) {
|
||||
new Flare( 4, 32 ).color( 0x44ffff, true ).show( sprite, 2f ) ;
|
||||
}
|
||||
state = State.SLEEPING;
|
||||
postpone( Sleep.SWS );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove( Buff buff ) {
|
||||
super.remove( buff );
|
||||
if (buff instanceof Terror) {
|
||||
sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE );
|
||||
state = State.HUNTING;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return Level.adjacent( pos, enemy.pos ) && !pacified;
|
||||
}
|
||||
|
||||
protected boolean getCloser( int target ) {
|
||||
|
||||
if (rooted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int step = Dungeon.findPath( this, pos, target,
|
||||
Level.passable,
|
||||
Level.fieldOfView );
|
||||
if (step != -1) {
|
||||
move( step );
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean getFurther( int target ) {
|
||||
int step = Dungeon.flee( this, pos, target,
|
||||
Level.passable,
|
||||
Level.fieldOfView );
|
||||
if (step != -1) {
|
||||
move( step );
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move( int step ) {
|
||||
super.move( step );
|
||||
|
||||
if (!flying) {
|
||||
Dungeon.level.mobPress( this );
|
||||
}
|
||||
}
|
||||
|
||||
protected float attackDelay() {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
protected boolean doAttack( Char enemy ) {
|
||||
|
||||
boolean visible = Dungeon.visible[pos];
|
||||
|
||||
if (visible) {
|
||||
sprite.attack( enemy.pos );
|
||||
} else {
|
||||
attack( enemy );
|
||||
}
|
||||
|
||||
spend( attackDelay() );
|
||||
|
||||
return !visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttackComplete() {
|
||||
attack( enemy );
|
||||
super.onAttackComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseSkill( Char enemy ) {
|
||||
return enemySeen && !paralysed ? defenseSkill : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseProc( Char enemy, int damage ) {
|
||||
if (!enemySeen && enemy == Dungeon.hero && ((Hero)enemy).subClass == HeroSubClass.ASSASSIN) {
|
||||
damage += Random.Int( 1, damage );
|
||||
Wound.hit( this );
|
||||
}
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
|
||||
Terror.recover( this );
|
||||
|
||||
if (state == State.SLEEPING) {
|
||||
state = State.WANDERING;
|
||||
}
|
||||
alerted = true;
|
||||
|
||||
super.damage( dmg, src );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
super.destroy();
|
||||
|
||||
Dungeon.level.mobs.remove( this );
|
||||
|
||||
if (Dungeon.hero.isAlive()) {
|
||||
|
||||
if (hostile) {
|
||||
Statistics.enemiesSlain++;
|
||||
Badges.validateMonstersSlain();
|
||||
Statistics.qualifiedForNoKilling = false;
|
||||
|
||||
if (Dungeon.nightMode) {
|
||||
Statistics.nightHunt++;
|
||||
} else {
|
||||
Statistics.nightHunt = 0;
|
||||
}
|
||||
Badges.validateNightHunter();
|
||||
}
|
||||
|
||||
if (Dungeon.hero.lvl <= maxLvl && EXP > 0) {
|
||||
Dungeon.hero.sprite.showStatus( CharSprite.POSITIVE, TXT_EXP, EXP );
|
||||
Dungeon.hero.earnExp( EXP );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
|
||||
super.die( cause );
|
||||
|
||||
if (Dungeon.hero.lvl <= maxLvl + 2) {
|
||||
dropLoot();
|
||||
}
|
||||
|
||||
if (Dungeon.hero.isAlive() && !Dungeon.visible[pos]) {
|
||||
GLog.i( TXT_DIED );
|
||||
}
|
||||
}
|
||||
|
||||
protected Object loot = null;
|
||||
protected float lootChance = 0;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void dropLoot() {
|
||||
if (loot != null && Random.Float() < lootChance) {
|
||||
Item item = null;
|
||||
if (loot instanceof Generator.Category) {
|
||||
|
||||
item = Generator.random( (Generator.Category)loot );
|
||||
|
||||
} else if (loot instanceof Class<?>) {
|
||||
|
||||
item = Generator.random( (Class<? extends Item>)loot );
|
||||
|
||||
} else {
|
||||
|
||||
item = (Item)loot;
|
||||
|
||||
}
|
||||
Dungeon.level.drop( item, pos ).sprite.drop();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean reset() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void beckon( int cell ) {
|
||||
|
||||
notice();
|
||||
|
||||
if (state != State.HUNTING) {
|
||||
state = State.WANDERING;
|
||||
}
|
||||
target = cell;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return "Real description is coming soon!";
|
||||
}
|
||||
|
||||
public void notice() {
|
||||
sprite.showAlert();
|
||||
}
|
||||
|
||||
public void yell( String str ) {
|
||||
GLog.n( "%s: \"%s\" ", name, str );
|
||||
}
|
||||
|
||||
public static abstract class NPC extends Mob {
|
||||
|
||||
{
|
||||
HP = HT = 1;
|
||||
EXP = 0;
|
||||
|
||||
hostile = false;
|
||||
state = State.PASSIVE;
|
||||
}
|
||||
|
||||
protected void throwItem() {
|
||||
Heap heap = Dungeon.level.heaps.get( pos );
|
||||
if (heap != null) {
|
||||
int n;
|
||||
do {
|
||||
n = pos + Level.NEIGHBOURS8[Random.Int( 8 )];
|
||||
} while (!Level.passable[n] && !Level.avoid[n]);
|
||||
Dungeon.level.drop( heap.pickUp(), n ).sprite.drop( pos );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beckon( int cell ) {
|
||||
}
|
||||
|
||||
abstract public void interact();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.Food;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Knuckles;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.MonkSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Monk extends Mob {
|
||||
|
||||
public static final String TXT_DISARM = "%s has knocked the %s from your hands!";
|
||||
|
||||
{
|
||||
name = "dwarf monk";
|
||||
spriteClass = MonkSprite.class;
|
||||
|
||||
HP = HT = 70;
|
||||
defenseSkill = 30;
|
||||
|
||||
EXP = 11;
|
||||
maxLvl = 21;
|
||||
|
||||
loot = new Food();
|
||||
lootChance = 0.083f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 12, 16 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float attackDelay() {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "parried";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
Imp.Quest.process( this );
|
||||
|
||||
super.die( cause );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
|
||||
if (Random.Int( 6 ) == 0 && enemy == Dungeon.hero) {
|
||||
|
||||
Hero hero = Dungeon.hero;
|
||||
KindOfWeapon weapon = hero.belongings.weapon;
|
||||
|
||||
if (weapon != null && !(weapon instanceof Knuckles) && !weapon.cursed) {
|
||||
hero.belongings.weapon = null;
|
||||
Dungeon.level.drop( weapon, hero.pos ).sprite.drop();
|
||||
GLog.w( TXT_DISARM, name, weapon.name() );
|
||||
}
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"These monks are fanatics, who devoted themselves to protecting their city's secrets from all aliens. " +
|
||||
"They don't use any armor or weapons, relying solely on the art of hand-to-hand combat.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Amok.class );
|
||||
IMMUNITIES.add( Terror.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.PiranhaSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Piranha extends Mob {
|
||||
|
||||
{
|
||||
name = "giant piranha";
|
||||
spriteClass = PiranhaSprite.class;
|
||||
|
||||
baseSpeed = 2f;
|
||||
|
||||
EXP = 0;
|
||||
}
|
||||
|
||||
public Piranha() {
|
||||
super();
|
||||
|
||||
HP = HT = 10 + Dungeon.depth * 5;
|
||||
defenseSkill = 10 + Dungeon.depth * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
if (!Level.water[pos]) {
|
||||
die( null );
|
||||
return true;
|
||||
} else {
|
||||
return super.act();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( Dungeon.depth, 4 + Dungeon.depth * 2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 20 + Dungeon.depth * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return Dungeon.depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
Dungeon.level.drop( new MysteryMeat(), pos ).sprite.drop();
|
||||
super.die( cause );
|
||||
|
||||
Statistics.piranhasKilled++;
|
||||
Badges.validatePiranhasKilled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getCloser( int target ) {
|
||||
|
||||
if (rooted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int step = Dungeon.findPath( this, pos, target,
|
||||
Level.water,
|
||||
Level.fieldOfView );
|
||||
if (step != -1) {
|
||||
move( step );
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getFurther( int target ) {
|
||||
int step = Dungeon.flee( this, pos, target,
|
||||
Level.water,
|
||||
Level.fieldOfView );
|
||||
if (step != -1) {
|
||||
move( step );
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"These carnivorous fish are not natural inhabitants of underground pools. " +
|
||||
"They were bred specifically to protect flooded treasure vaults.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Burning.class );
|
||||
IMMUNITIES.add( Paralysis.class );
|
||||
IMMUNITIES.add( ToxicGas.class );
|
||||
IMMUNITIES.add( Roots.class );
|
||||
IMMUNITIES.add( Frost.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.RatSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Rat extends Mob {
|
||||
|
||||
{
|
||||
name = "marsupial rat";
|
||||
spriteClass = RatSprite.class;
|
||||
|
||||
HP = HT = 8;
|
||||
defenseSkill = 3;
|
||||
|
||||
maxLvl = 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 1, 5 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
Ghost.Quest.process( pos );
|
||||
|
||||
super.die( cause );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Marsupial rats are aggressive, but rather weak denizens " +
|
||||
"of the sewers. They can be dangerous only in big numbers.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Leech;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ScorpioSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Scorpio extends Mob {
|
||||
|
||||
{
|
||||
name = "scorpio";
|
||||
spriteClass = ScorpioSprite.class;
|
||||
|
||||
HP = HT = 95;
|
||||
defenseSkill = 24;
|
||||
viewDistance = Light.DISTANCE;
|
||||
|
||||
EXP = 14;
|
||||
maxLvl = 25;
|
||||
|
||||
loot = new PotionOfHealing();
|
||||
lootChance = 0.125f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 20, 32 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 36;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return !Level.adjacent( pos, enemy.pos ) && Ballistica.cast( pos, enemy.pos, false, true ) == enemy.pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
Buff.prolong( enemy, Cripple.class, Cripple.DURATION );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getCloser( int target ) {
|
||||
if (state == State.HUNTING) {
|
||||
return enemySeen && getFurther( target );
|
||||
} else {
|
||||
return super.getCloser( target );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropLoot() {
|
||||
if (Random.Int( 8 ) == 0) {
|
||||
Dungeon.level.drop( new PotionOfHealing(), pos ).sprite.drop();
|
||||
} else if (Random.Int( 6 ) == 0) {
|
||||
Dungeon.level.drop( new MysteryMeat(), pos ).sprite.drop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"These huge arachnid-like demonic creatures avoid close combat by all means, " +
|
||||
"firing crippling serrated spikes from long distances.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( Leech.class );
|
||||
RESISTANCES.add( Poison.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.SeniorSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Senior extends Monk {
|
||||
|
||||
{
|
||||
name = "senior monk";
|
||||
spriteClass = SeniorSprite.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 12, 20 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (Random.Int( 10 ) == 0) {
|
||||
Buff.prolong( enemy, Paralysis.class, 1.1f );
|
||||
}
|
||||
return super.attackProc( enemy, damage );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
Badges.validateRare( this );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.Camera;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SparkParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.LightningTrap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ShamanSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Callback;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Shaman extends Mob implements Callback {
|
||||
|
||||
private static final float TIME_TO_ZAP = 2f;
|
||||
|
||||
private static final String TXT_LIGHTNING_KILLED = "%s's lightning bolt killed you...";
|
||||
|
||||
{
|
||||
name = "gnoll shaman";
|
||||
spriteClass = ShamanSprite.class;
|
||||
|
||||
HP = HT = 18;
|
||||
defenseSkill = 8;
|
||||
|
||||
EXP = 6;
|
||||
maxLvl = 14;
|
||||
|
||||
loot = Generator.Category.SCROLL;
|
||||
lootChance = 0.33f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 2, 6 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 11;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return Ballistica.cast( pos, enemy.pos, false, true ) == enemy.pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doAttack( Char enemy ) {
|
||||
|
||||
if (Level.distance( pos, enemy.pos ) <= 1) {
|
||||
|
||||
return super.doAttack( enemy );
|
||||
|
||||
} else {
|
||||
|
||||
boolean visible = Level.fieldOfView[pos] || Level.fieldOfView[enemy.pos];
|
||||
if (visible) {
|
||||
((ShamanSprite)sprite).zap( enemy.pos );
|
||||
}
|
||||
|
||||
spend( TIME_TO_ZAP );
|
||||
|
||||
if (hit( this, enemy, true )) {
|
||||
int dmg = Random.Int( 2, 12 );
|
||||
if (Level.water[enemy.pos] && !enemy.flying) {
|
||||
dmg *= 1.5f;
|
||||
}
|
||||
enemy.damage( dmg, LightningTrap.LIGHTNING );
|
||||
|
||||
enemy.sprite.centerEmitter().burst( SparkParticle.FACTORY, 3 );
|
||||
enemy.sprite.flash();
|
||||
|
||||
if (enemy == Dungeon.hero) {
|
||||
|
||||
Camera.main.shake( 2, 0.3f );
|
||||
|
||||
if (!enemy.isAlive()) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.MOB,
|
||||
Utils.indefinite( name ), Dungeon.depth ) );
|
||||
GLog.n( TXT_LIGHTNING_KILLED, name );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
|
||||
}
|
||||
|
||||
return !visible;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call() {
|
||||
next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"The most intelligent gnolls can master shamanistic magic. Gnoll shamans prefer " +
|
||||
"battle spells to compensate for lack of might, not hesitating to use them " +
|
||||
"on those who question their status in a tribe.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( LightningTrap.Electricity.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ShieldedSprite;
|
||||
|
||||
public class Shielded extends Brute {
|
||||
|
||||
{
|
||||
name = "shielded brute";
|
||||
spriteClass = ShieldedSprite.class;
|
||||
|
||||
defenseSkill = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "blocked";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
Badges.validateRare( this );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.SkeletonSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Skeleton extends Mob {
|
||||
|
||||
private static final String TXT_HERO_KILLED = "You were killed by the explosion of bones...";
|
||||
|
||||
{
|
||||
name = "skeleton";
|
||||
spriteClass = SkeletonSprite.class;
|
||||
|
||||
HP = HT = 25;
|
||||
defenseSkill = 9;
|
||||
|
||||
EXP = 5;
|
||||
maxLvl = 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 3, 8 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
|
||||
super.die( cause );
|
||||
|
||||
boolean heroKilled = false;
|
||||
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
|
||||
Char ch = findChar( pos + Level.NEIGHBOURS8[i] );
|
||||
if (ch != null && ch.isAlive()) {
|
||||
int damage = Math.max( 0, damageRoll() - Random.IntRange( 0, ch.dr() / 2 ) );
|
||||
ch.damage( damage, this );
|
||||
if (ch == Dungeon.hero && !ch.isAlive()) {
|
||||
heroKilled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
Sample.INSTANCE.play( Assets.SND_BONES );
|
||||
}
|
||||
|
||||
if (heroKilled) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.MOB, Utils.indefinite( name ), Dungeon.depth ) );
|
||||
GLog.n( TXT_HERO_KILLED );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropLoot() {
|
||||
if (Random.Int( 5 ) == 0) {
|
||||
Item loot = Generator.random( Generator.Category.WEAPON );
|
||||
for (int i=0; i < 2; i++) {
|
||||
Item l = Generator.random( Generator.Category.WEAPON );
|
||||
if (l.level < loot.level) {
|
||||
loot = l;
|
||||
}
|
||||
}
|
||||
Dungeon.level.drop( loot, pos ).sprite.drop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "blocked";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Skeletons are composed of corpses bones from unlucky adventurers and inhabitants of the dungeon, " +
|
||||
"animated by emanations of evil magic from the depths below. After they have been " +
|
||||
"damaged enough, they disintegrate in an explosion of bones.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Death.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Web;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.MysteryMeat;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.SpinnerSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Spinner extends Mob {
|
||||
|
||||
{
|
||||
name = "cave spinner";
|
||||
spriteClass = SpinnerSprite.class;
|
||||
|
||||
HP = HT = 50;
|
||||
defenseSkill = 14;
|
||||
|
||||
EXP = 9;
|
||||
maxLvl = 16;
|
||||
|
||||
loot = new MysteryMeat();
|
||||
lootChance = 0.125f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 12, 16 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void nowhereToRun() {
|
||||
if (buff( Terror.class ) == null) {
|
||||
state = State.HUNTING;
|
||||
} else {
|
||||
super.nowhereToRun();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
boolean result = super.act();
|
||||
|
||||
if (state == State.FLEEING && buff( Terror.class ) == null &&
|
||||
enemySeen && enemy.buff( Poison.class ) == null) {
|
||||
|
||||
state = State.HUNTING;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
Buff.affect( enemy, Poison.class ).set( Random.Int( 5, 7 ) * Poison.durationFactor( enemy ) );
|
||||
state = State.FLEEING;
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move( int step ) {
|
||||
if (state == State.FLEEING) {
|
||||
GameScene.add( Blob.seed( pos, Random.Int( 5, 7 ), Web.class ) );
|
||||
}
|
||||
super.move( step );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"These greenish furry cave spiders try to avoid direct combat, preferring to wait in the distance " +
|
||||
"while their victim, entangled in the spinner's excreted cobweb, slowly dies from their poisonous bite.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( Poison.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Roots.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Journal;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon.Enchantment;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Leech;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MeleeWeapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.StatueSprite;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Statue extends Mob {
|
||||
|
||||
{
|
||||
name = "animated statue";
|
||||
spriteClass = StatueSprite.class;
|
||||
|
||||
EXP = 0;
|
||||
state = State.PASSIVE;
|
||||
}
|
||||
|
||||
private Weapon weapon;
|
||||
|
||||
public Statue() {
|
||||
super();
|
||||
|
||||
do {
|
||||
weapon = (Weapon)Generator.random( Generator.Category.WEAPON );
|
||||
} while (!(weapon instanceof MeleeWeapon) || weapon.level < 0);
|
||||
|
||||
weapon.identify();
|
||||
weapon.enchant( Enchantment.random() );
|
||||
|
||||
HP = HT = 15 + Dungeon.depth * 5;
|
||||
defenseSkill = 4 + Dungeon.depth;
|
||||
}
|
||||
|
||||
private static final String WEAPON = "weapon";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( WEAPON, weapon );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
weapon = (Weapon)bundle.get( WEAPON );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean act() {
|
||||
if (Dungeon.visible[pos]) {
|
||||
Journal.add( Journal.Feature.STATUE );
|
||||
}
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( weapon.MIN, weapon.MAX );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return (int)((9 + Dungeon.depth) * weapon.ACU);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float attackDelay() {
|
||||
return weapon.DLY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return Dungeon.depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
|
||||
if (state == State.PASSIVE) {
|
||||
state = State.HUNTING;
|
||||
}
|
||||
|
||||
super.damage( dmg, src );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
weapon.proc( this, enemy, damage );
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beckon( int cell ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
Dungeon.level.drop( weapon, pos ).sprite.drop();
|
||||
super.die( cause );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Journal.remove( Journal.Feature.STATUE );
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
state = State.PASSIVE;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"You would think that it's just another ugly statue of this dungeon, but its red glowing eyes give itself away. " +
|
||||
"While the statue itself is made of stone, the _" + weapon.name() + "_, it's wielding, looks real.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( ToxicGas.class );
|
||||
RESISTANCES.add( Poison.class );
|
||||
RESISTANCES.add( Death.class );
|
||||
RESISTANCES.add( ScrollOfPsionicBlast.class );
|
||||
IMMUNITIES.add( Leech.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Light;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfLullaby;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Leech;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.SuccubusSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Succubus extends Mob {
|
||||
|
||||
private static final int BLINK_DELAY = 5;
|
||||
|
||||
private int delay = 0;
|
||||
|
||||
{
|
||||
name = "succubus";
|
||||
spriteClass = SuccubusSprite.class;
|
||||
|
||||
HP = HT = 80;
|
||||
defenseSkill = 25;
|
||||
viewDistance = Light.DISTANCE;
|
||||
|
||||
EXP = 12;
|
||||
maxLvl = 25;
|
||||
|
||||
loot = new ScrollOfLullaby();
|
||||
lootChance = 0.05f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 15, 25 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
|
||||
if (Random.Int( 3 ) == 0) {
|
||||
Buff.affect( enemy, Charm.class, Charm.durationFactor( enemy ) * Random.IntRange( 2, 5 ) );
|
||||
enemy.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
|
||||
Sample.INSTANCE.play( Assets.SND_CHARMS );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getCloser( int target ) {
|
||||
if (Level.fieldOfView[target] && Level.distance( pos, target ) > 2 && delay <= 0) {
|
||||
|
||||
blink( target );
|
||||
spend( -1 / speed() );
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
delay--;
|
||||
return super.getCloser( target );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void blink( int target ) {
|
||||
|
||||
int cell = Ballistica.cast( pos, target, true, true );
|
||||
|
||||
if (Actor.findChar( cell ) != null && Ballistica.distance > 1) {
|
||||
cell = Ballistica.trace[Ballistica.distance - 2];
|
||||
}
|
||||
|
||||
WandOfBlink.appear( this, cell );
|
||||
|
||||
delay = BLINK_DELAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 40;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"The succubi are demons that look like seductive (in a slightly gothic way) girls. Using its magic, the succubus " +
|
||||
"can charm a hero, who will become unable to attack anything until the charm wears off.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( Leech.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Sleep.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.SwarmSprite;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Swarm extends Mob {
|
||||
|
||||
{
|
||||
name = "swarm of flies";
|
||||
spriteClass = SwarmSprite.class;
|
||||
|
||||
HP = HT = 80;
|
||||
defenseSkill = 5;
|
||||
|
||||
maxLvl = 10;
|
||||
|
||||
flying = true;
|
||||
}
|
||||
|
||||
private static final float SPLIT_DELAY = 1f;
|
||||
|
||||
int generation = 0;
|
||||
|
||||
private static final String GENERATION = "generation";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( GENERATION, generation );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
generation = bundle.getInt( GENERATION );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 1, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseProc( Char enemy, int damage ) {
|
||||
|
||||
if (HP >= damage + 2) {
|
||||
ArrayList<Integer> candidates = new ArrayList<Integer>();
|
||||
boolean[] passable = Level.passable;
|
||||
|
||||
int[] neighbours = {pos + 1, pos - 1, pos + Level.WIDTH, pos - Level.WIDTH};
|
||||
for (int n : neighbours) {
|
||||
if (passable[n] && Actor.findChar( n ) == null) {
|
||||
candidates.add( n );
|
||||
}
|
||||
}
|
||||
|
||||
if (candidates.size() > 0) {
|
||||
|
||||
Swarm clone = split();
|
||||
clone.HP = (HP - damage) / 2;
|
||||
clone.pos = Random.element( candidates );
|
||||
clone.state = State.HUNTING;
|
||||
|
||||
if (Dungeon.level.map[clone.pos] == Terrain.DOOR) {
|
||||
Door.enter( clone.pos );
|
||||
}
|
||||
|
||||
GameScene.add( clone, SPLIT_DELAY );
|
||||
Actor.addDelayed( new Pushing( clone, pos, clone.pos ), -1 );
|
||||
|
||||
HP -= clone.HP;
|
||||
}
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "evaded";
|
||||
}
|
||||
|
||||
private Swarm split() {
|
||||
Swarm clone = new Swarm();
|
||||
clone.generation = generation + 1;
|
||||
if (buff( Burning.class ) != null) {
|
||||
Buff.affect( clone, Burning.class ).reignite( clone );
|
||||
}
|
||||
if (buff( Poison.class ) != null) {
|
||||
Buff.affect( clone, Poison.class ).set( 2 );
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropLoot() {
|
||||
if (Random.Int( 5 * (generation + 1) ) == 0) {
|
||||
Dungeon.level.drop( new PotionOfHealing(), pos ).sprite.drop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"The deadly swarm of flies buzzes angrily. Every non-magical attack " +
|
||||
"will split it into two smaller but equally dangerous swarms.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges.Badge;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.TomeOfMastery;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMagicMapping;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.TenguSprite;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Tengu extends Mob {
|
||||
|
||||
private static final int JUMP_DELAY = 5;
|
||||
|
||||
{
|
||||
name = "Tengu";
|
||||
spriteClass = TenguSprite.class;
|
||||
|
||||
HP = HT = 120;
|
||||
EXP = 20;
|
||||
defenseSkill = 20;
|
||||
}
|
||||
|
||||
private int timeToJump = JUMP_DELAY;
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 8, 15 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
|
||||
Badges.Badge badgeToCheck = null;
|
||||
switch (Dungeon.hero.heroClass) {
|
||||
case WARRIOR:
|
||||
badgeToCheck = Badge.MASTERY_WARRIOR;
|
||||
break;
|
||||
case MAGE:
|
||||
badgeToCheck = Badge.MASTERY_MAGE;
|
||||
break;
|
||||
case ROGUE:
|
||||
badgeToCheck = Badge.MASTERY_ROGUE;
|
||||
break;
|
||||
case HUNTRESS:
|
||||
badgeToCheck = Badge.MASTERY_HUNTRESS;
|
||||
break;
|
||||
}
|
||||
if (!Badges.isUnlocked( badgeToCheck )) {
|
||||
Dungeon.level.drop( new TomeOfMastery(), pos ).sprite.drop();
|
||||
}
|
||||
|
||||
GameScene.bossSlain();
|
||||
Dungeon.level.drop( new SkeletonKey( Dungeon.depth ), pos ).sprite.drop();
|
||||
super.die( cause );
|
||||
|
||||
Badges.validateBossSlain();
|
||||
|
||||
yell( "Free at last..." );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getCloser( int target ) {
|
||||
if (Level.fieldOfView[target]) {
|
||||
jump();
|
||||
return true;
|
||||
} else {
|
||||
return super.getCloser( target );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return Ballistica.cast( pos, enemy.pos, false, true ) == enemy.pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doAttack( Char enemy ) {
|
||||
timeToJump--;
|
||||
if (timeToJump <= 0 && Level.adjacent( pos, enemy.pos )) {
|
||||
jump();
|
||||
return true;
|
||||
} else {
|
||||
return super.doAttack( enemy );
|
||||
}
|
||||
}
|
||||
|
||||
private void jump() {
|
||||
timeToJump = JUMP_DELAY;
|
||||
|
||||
for (int i=0; i < 4; i++) {
|
||||
int trapPos;
|
||||
do {
|
||||
trapPos = Random.Int( Level.LENGTH );
|
||||
} while (!Level.fieldOfView[trapPos] || !Level.passable[trapPos]);
|
||||
|
||||
if (Dungeon.level.map[trapPos] == Terrain.INACTIVE_TRAP) {
|
||||
Level.set( trapPos, Terrain.POISON_TRAP );
|
||||
GameScene.updateMap( trapPos );
|
||||
ScrollOfMagicMapping.discover( trapPos );
|
||||
}
|
||||
}
|
||||
|
||||
int newPos;
|
||||
do {
|
||||
newPos = Random.Int( Level.LENGTH );
|
||||
} while (
|
||||
!Level.fieldOfView[newPos] ||
|
||||
!Level.passable[newPos] ||
|
||||
Level.adjacent( newPos, enemy.pos ) ||
|
||||
Actor.findChar( newPos ) != null);
|
||||
|
||||
sprite.move( pos, newPos );
|
||||
move( newPos );
|
||||
|
||||
if (Dungeon.visible[newPos]) {
|
||||
CellEmitter.get( newPos ).burst( Speck.factory( Speck.WOOL ), 6 );
|
||||
Sample.INSTANCE.play( Assets.SND_PUFF );
|
||||
}
|
||||
|
||||
spend( 1 / speed() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notice() {
|
||||
super.notice();
|
||||
yell( "Gotcha, " + Dungeon.hero.heroClass.title() + "!" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"Tengu are members of the ancient assassins clan, which is also called Tengu. " +
|
||||
"These assassins are noted for extensive use of shuriken and traps.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( ToxicGas.class );
|
||||
RESISTANCES.add( Poison.class );
|
||||
RESISTANCES.add( Death.class );
|
||||
RESISTANCES.add( ScrollOfPsionicBlast.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfHaggler;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ThiefSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Thief extends Mob {
|
||||
|
||||
protected static final String TXT_STOLE = "%s stole %s from you!";
|
||||
protected static final String TXT_CARRIES = "\n\n%s is carrying a _%s_. Stolen obviously.";
|
||||
|
||||
public Item item;
|
||||
|
||||
{
|
||||
name = "crazy thief";
|
||||
spriteClass = ThiefSprite.class;
|
||||
|
||||
HP = HT = 20;
|
||||
defenseSkill = 12;
|
||||
|
||||
EXP = 5;
|
||||
maxLvl = 10;
|
||||
|
||||
loot = RingOfHaggler.class;
|
||||
lootChance = 0.01f;
|
||||
}
|
||||
|
||||
private static final String ITEM = "item";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( ITEM, item );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
item = (Item)bundle.get( ITEM );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 1, 7 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float attackDelay() {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void nowhereToRun() {
|
||||
if (buff( Terror.class ) == null) {
|
||||
sprite.showStatus( CharSprite.NEGATIVE, TXT_RAGE );
|
||||
state = State.HUNTING;
|
||||
} else {
|
||||
super.nowhereToRun();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
|
||||
super.die( cause );
|
||||
|
||||
if (item != null) {
|
||||
Dungeon.level.drop( item, pos ).sprite.drop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (item == null && enemy instanceof Hero && steal( (Hero)enemy )) {
|
||||
state = State.FLEEING;
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseProc(Char enemy, int damage) {
|
||||
if (state == State.FLEEING) {
|
||||
Dungeon.level.drop( new Gold(), pos ).sprite.drop();
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
protected boolean steal( Hero hero ) {
|
||||
|
||||
Item item = hero.belongings.randomUnequipped();
|
||||
if (item != null) {
|
||||
|
||||
GLog.w( TXT_STOLE, this.name, item.name() );
|
||||
|
||||
item.detachAll( hero.belongings.backpack );
|
||||
this.item = item;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
String desc =
|
||||
"Deeper levels of the dungeon have always been a hiding place for all kinds of criminals. " +
|
||||
"Not all of them could keep a clear mind during their extended periods so far from daylight. Long ago, " +
|
||||
"these crazy thieves and bandits have forgotten who they are and why they steal.";
|
||||
|
||||
if (item != null) {
|
||||
desc += String.format( TXT_CARRIES, Utils.capitalize( this.name ), item.name() );
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Weakness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.WarlockSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Callback;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Warlock extends Mob implements Callback {
|
||||
|
||||
private static final float TIME_TO_ZAP = 1f;
|
||||
|
||||
private static final String TXT_SHADOWBOLT_KILLED = "%s's shadow bolt killed you...";
|
||||
|
||||
{
|
||||
name = "dwarf warlock";
|
||||
spriteClass = WarlockSprite.class;
|
||||
|
||||
HP = HT = 70;
|
||||
defenseSkill = 18;
|
||||
|
||||
EXP = 11;
|
||||
maxLvl = 21;
|
||||
|
||||
loot = Generator.Category.POTION;
|
||||
lootChance = 0.83f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 12, 20 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 25;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return Ballistica.cast( pos, enemy.pos, false, true ) == enemy.pos;
|
||||
}
|
||||
|
||||
protected boolean doAttack( Char enemy ) {
|
||||
|
||||
if (Level.adjacent( pos, enemy.pos )) {
|
||||
|
||||
return super.doAttack( enemy );
|
||||
|
||||
} else {
|
||||
|
||||
boolean visible = Level.fieldOfView[pos] || Level.fieldOfView[enemy.pos];
|
||||
if (visible) {
|
||||
((WarlockSprite)sprite).zap( enemy.pos );
|
||||
} else {
|
||||
zap();
|
||||
}
|
||||
|
||||
return !visible;
|
||||
}
|
||||
}
|
||||
|
||||
private void zap() {
|
||||
spend( TIME_TO_ZAP );
|
||||
|
||||
if (hit( this, enemy, true )) {
|
||||
if (enemy == Dungeon.hero && Random.Int( 2 ) == 0) {
|
||||
Buff.prolong( enemy, Weakness.class, Weakness.duration( enemy ) );
|
||||
}
|
||||
|
||||
int dmg = Random.Int( 12, 18 );
|
||||
enemy.damage( dmg, this );
|
||||
|
||||
if (!enemy.isAlive() && enemy == Dungeon.hero) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.MOB,
|
||||
Utils.indefinite( name ), Dungeon.depth ) );
|
||||
GLog.n( TXT_SHADOWBOLT_KILLED, name );
|
||||
}
|
||||
} else {
|
||||
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
|
||||
}
|
||||
}
|
||||
|
||||
public void onZapComplete() {
|
||||
zap();
|
||||
next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call() {
|
||||
next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"When dwarves' interests have shifted from engineering to arcane arts, " +
|
||||
"warlocks have come to power in the city. They started with elemental magic, " +
|
||||
"but soon switched to demonology and necromancy.";
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( Death.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.tweeners.AlphaTweener;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.WraithSprite;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Wraith extends Mob {
|
||||
|
||||
private static final float SPAWN_DELAY = 2f;
|
||||
|
||||
private int level;
|
||||
|
||||
{
|
||||
name = "wraith";
|
||||
spriteClass = WraithSprite.class;
|
||||
|
||||
HP = HT = 1;
|
||||
EXP = 0;
|
||||
|
||||
flying = true;
|
||||
}
|
||||
|
||||
private static final String LEVEL = "level";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( LEVEL, level );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
level = bundle.getInt( LEVEL );
|
||||
adjustStats( level );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 1, 3 + level );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 10 + level;
|
||||
}
|
||||
|
||||
public void adjustStats( int level ) {
|
||||
this.level = level;
|
||||
defenseSkill = attackSkill( null ) * 5;
|
||||
enemySeen = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defenseVerb() {
|
||||
return "evaded";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reset() {
|
||||
state = State.WANDERING;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return
|
||||
"A wraith is a vengeful spirit of a sinner, whose grave or tomb was disturbed. " +
|
||||
"Being an ethereal entity, it is very hard to hit with a regular weapon.";
|
||||
}
|
||||
|
||||
public static void spawnAround( int pos ) {
|
||||
for (int n : Level.NEIGHBOURS4) {
|
||||
int cell = pos + n;
|
||||
if (Level.passable[cell] && Actor.findChar( cell ) == null) {
|
||||
spawnAt( cell );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Wraith spawnAt( int pos ) {
|
||||
if (Level.passable[pos] && Actor.findChar( pos ) == null) {
|
||||
|
||||
Wraith w = new Wraith();
|
||||
w.adjustStats( Dungeon.depth );
|
||||
w.pos = pos;
|
||||
w.state = State.HUNTING;
|
||||
GameScene.add( w, SPAWN_DELAY );
|
||||
|
||||
w.sprite.alpha( 0 );
|
||||
w.sprite.parent.add( new AlphaTweener( w.sprite, 1, 0.5f ) );
|
||||
|
||||
w.sprite.emitter().burst( ShadowParticle.CURSE, 5 );
|
||||
|
||||
return w;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Death.class );
|
||||
IMMUNITIES.add( Terror.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Amok;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Sleep;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfPsionicBlast;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Death;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.BurningFistSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.LarvaSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.RottingFistSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.YogSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Yog extends Mob {
|
||||
|
||||
{
|
||||
name = "Yog-Dzewa";
|
||||
spriteClass = YogSprite.class;
|
||||
|
||||
HP = HT = 300;
|
||||
|
||||
EXP = 50;
|
||||
|
||||
state = State.PASSIVE;
|
||||
}
|
||||
|
||||
private static final String TXT_DESC =
|
||||
"Yog-Dzewa is an Old God, a powerful entity from the realms of chaos. A century ago, the ancient dwarves " +
|
||||
"barely won the war against its army of demons, but were unable to kill the god itself. Instead, they then " +
|
||||
"imprisoned it in the halls below their city, believing it to be too weak to rise ever again.";
|
||||
|
||||
private static int fistsCount = 0;
|
||||
|
||||
public Yog() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void spawnFists() {
|
||||
RottingFist fist1 = new RottingFist();
|
||||
BurningFist fist2 = new BurningFist();
|
||||
|
||||
do {
|
||||
fist1.pos = pos + Level.NEIGHBOURS8[Random.Int( 8 )];
|
||||
fist2.pos = pos + Level.NEIGHBOURS8[Random.Int( 8 )];
|
||||
} while (!Level.passable[fist1.pos] || !Level.passable[fist2.pos] || fist1.pos == fist2.pos);
|
||||
|
||||
GameScene.add( fist1 );
|
||||
GameScene.add( fist2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage( int dmg, Object src ) {
|
||||
|
||||
if (fistsCount > 0) {
|
||||
|
||||
for (Mob mob : Dungeon.level.mobs) {
|
||||
if (mob instanceof BurningFist || mob instanceof RottingFist) {
|
||||
mob.beckon( pos );
|
||||
}
|
||||
}
|
||||
|
||||
dmg >>= fistsCount;
|
||||
}
|
||||
|
||||
super.damage( dmg, src );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenseProc( Char enemy, int damage ) {
|
||||
|
||||
ArrayList<Integer> spawnPoints = new ArrayList<Integer>();
|
||||
|
||||
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
|
||||
int p = pos + Level.NEIGHBOURS8[i];
|
||||
if (Actor.findChar( p ) == null && (Level.passable[p] || Level.avoid[p])) {
|
||||
spawnPoints.add( p );
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnPoints.size() > 0) {
|
||||
Larva larva = new Larva();
|
||||
larva.pos = Random.element( spawnPoints );
|
||||
|
||||
GameScene.add( larva );
|
||||
Actor.addDelayed( new Pushing( larva, pos, larva.pos ), -1 );
|
||||
}
|
||||
|
||||
return super.defenseProc(enemy, damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beckon( int cell ) {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
|
||||
for (Mob mob : (Iterable<Mob>)Dungeon.level.mobs.clone()) {
|
||||
if (mob instanceof BurningFist || mob instanceof RottingFist) {
|
||||
mob.die( cause );
|
||||
}
|
||||
}
|
||||
|
||||
GameScene.bossSlain();
|
||||
Dungeon.level.drop( new SkeletonKey( Dungeon.depth ), pos ).sprite.drop();
|
||||
super.die( cause );
|
||||
|
||||
yell( "..." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notice() {
|
||||
super.notice();
|
||||
yell( "Hope is an illusion..." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return TXT_DESC;
|
||||
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
|
||||
IMMUNITIES.add( Death.class );
|
||||
IMMUNITIES.add( Terror.class );
|
||||
IMMUNITIES.add( Amok.class );
|
||||
IMMUNITIES.add( Charm.class );
|
||||
IMMUNITIES.add( Sleep.class );
|
||||
IMMUNITIES.add( Burning.class );
|
||||
IMMUNITIES.add( ToxicGas.class );
|
||||
IMMUNITIES.add( ScrollOfPsionicBlast.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
|
||||
public static class RottingFist extends Mob {
|
||||
|
||||
private static final int REGENERATION = 4;
|
||||
|
||||
{
|
||||
name = "rotting fist";
|
||||
spriteClass = RottingFistSprite.class;
|
||||
|
||||
HP = HT = 300;
|
||||
defenseSkill = 25;
|
||||
|
||||
EXP = 0;
|
||||
|
||||
state = State.WANDERING;
|
||||
}
|
||||
|
||||
public RottingFist() {
|
||||
super();
|
||||
fistsCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
fistsCount--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 36;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 24, 36 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackProc( Char enemy, int damage ) {
|
||||
if (Random.Int( 3 ) == 0) {
|
||||
Buff.affect( enemy, Ooze.class );
|
||||
enemy.sprite.burst( 0xFF000000, 5 );
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
|
||||
if (Level.water[pos] && HP < HT) {
|
||||
sprite.emitter().burst( ShadowParticle.UP, 2 );
|
||||
HP += REGENERATION;
|
||||
}
|
||||
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return TXT_DESC;
|
||||
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( ToxicGas.class );
|
||||
RESISTANCES.add( Death.class );
|
||||
RESISTANCES.add( ScrollOfPsionicBlast.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Amok.class );
|
||||
IMMUNITIES.add( Sleep.class );
|
||||
IMMUNITIES.add( Terror.class );
|
||||
IMMUNITIES.add( Poison.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BurningFist extends Mob {
|
||||
|
||||
{
|
||||
name = "burning fist";
|
||||
spriteClass = BurningFistSprite.class;
|
||||
|
||||
HP = HT = 200;
|
||||
defenseSkill = 25;
|
||||
|
||||
EXP = 0;
|
||||
|
||||
state = State.WANDERING;
|
||||
}
|
||||
|
||||
public BurningFist() {
|
||||
super();
|
||||
fistsCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die( Object cause ) {
|
||||
super.die( cause );
|
||||
fistsCount--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 36;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 20, 32 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canAttack( Char enemy ) {
|
||||
return Ballistica.cast( pos, enemy.pos, false, true ) == enemy.pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean attack( Char enemy ) {
|
||||
|
||||
if (!Level.adjacent( pos, enemy.pos )) {
|
||||
spend( attackDelay() );
|
||||
|
||||
if (hit( this, enemy, true )) {
|
||||
|
||||
int dmg = damageRoll();
|
||||
enemy.damage( dmg, this );
|
||||
|
||||
enemy.sprite.bloodBurstA( sprite.center(), dmg );
|
||||
enemy.sprite.flash();
|
||||
|
||||
if (!enemy.isAlive() && enemy == Dungeon.hero) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.BOSS, name, Dungeon.depth ) );
|
||||
GLog.n( TXT_KILL, name );
|
||||
}
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
enemy.sprite.showStatus( CharSprite.NEUTRAL, enemy.defenseVerb() );
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return super.attack( enemy );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean act() {
|
||||
|
||||
for (int i=0; i < Level.NEIGHBOURS9.length; i++) {
|
||||
GameScene.add( Blob.seed( pos + Level.NEIGHBOURS9[i], 2, Fire.class ) );
|
||||
}
|
||||
|
||||
return super.act();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return TXT_DESC;
|
||||
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> RESISTANCES = new HashSet<Class<?>>();
|
||||
static {
|
||||
RESISTANCES.add( ToxicGas.class );
|
||||
RESISTANCES.add( Death.class );
|
||||
RESISTANCES.add( ScrollOfPsionicBlast.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> resistances() {
|
||||
return RESISTANCES;
|
||||
}
|
||||
|
||||
private static final HashSet<Class<?>> IMMUNITIES = new HashSet<Class<?>>();
|
||||
static {
|
||||
IMMUNITIES.add( Amok.class );
|
||||
IMMUNITIES.add( Sleep.class );
|
||||
IMMUNITIES.add( Terror.class );
|
||||
IMMUNITIES.add( Burning.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<Class<?>> immunities() {
|
||||
return IMMUNITIES;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Larva extends Mob {
|
||||
|
||||
{
|
||||
name = "god's larva";
|
||||
spriteClass = LarvaSprite.class;
|
||||
|
||||
HP = HT = 25;
|
||||
defenseSkill = 20;
|
||||
|
||||
EXP = 0;
|
||||
|
||||
state = State.HUNTING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackSkill( Char target ) {
|
||||
return 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageRoll() {
|
||||
return Random.NormalIntRange( 15, 20 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dr() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return TXT_DESC;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user